Archive for the ‘JavaScript’ Category

Color Picker App v2 update

Thursday, July 16th, 2009

I haven’t forgotten v2 of the Color Picker App & it’s something I’ve been wanting to work on. Unfortunately I have other projects that pay the bills taking priority. I wanted to share a couple of ideas I’ve been toying with and get some feedback.

I’m planning to completely drop reliance on the X Library. I had toyed with the idea of doing some sort of flash based thing, but I’m thinking of using jQuery, YUI, or both instead.

I’m keeping the server side code PHP based and thinking of using Symfony, the Zend Framework, or something with user handling already built in - like Drupal (unlikely). Part of the reason for user logins is so people can submit/maintain color schemes.

I’m thinking of making it open source so people can host their own server full of color schemes. I’ll pull out the Firewheel Design ColorBurn feed and make the color feed section pluggable so people could write their own plugins for other services or completely random color schemes.

I’m hoping to make the color schemes more dynamic, but I’m not quite sure how to go about wrapping color swatches. From what I remember v1 requires 4 colors (that’s how many is in the ColorBurn widget). Most of the code is dynamic and simply loops through the array of color swatches, but the current floating & such will more than likely break if it doesn’t have exactly 4 colors.

I’m wanting to set it up so that there will be more choices than just the 3 of default color order, light to dark, & dark to light. I’d like to set it up so that the color feed could specify which color belonged to which class category (i.e. page text, page background, etc) by default. Maybe even define a default reverse order. I will still have the light to dark & dark to light. I may include a default color order based on the order the colors are first added to an array in order to have yet another possible way of viewing the colors.

I’m wanting to add drag & drop as well as color wheel / RGB / hex color selector for each class.

I’d like to make it a full page view with a draggable/clickable icon to pop open the color picker app.

That last brings me to something I was thinking about, but considering all of the various possibilities I’m not sure how viable it would be. Call me crazy, but I think it’d be cool if people could include the color app js file and whatever external js libs were needed to their own site page. It would then scan through all of the html elements; make a list of elements, classes, and id’s; and present them for possibly color changing/styling. The other possibility which might be better is for it to scan through the attached css files and only add the given css selectors to the list - thus giving the end user more control over what they were able to style.

This does cause problems with trying to automatically display color sets on a page. The end user would have to manually set all of the elements/classes/id’s or css selectors and their resulting color set may be near completely useless to somebody else who’s using different classes & id’s.

  • Share/Save/Bookmark

Annoying Failure to Auto-Complete

Sunday, June 21st, 2009

I’ve not bothered much with the adobe groups website… Partly because I don’t use adobe products, but also because Adobe is using the autocomplete=”off” attribute on the password input field… This means due to my already decreased interest in actually using the website this makes it even more of a pain to do things that *should* be very very *simple* like saying “Yes, I do want to go to <CFLunch/>”.

Considering all I do with my adobe groups account is RSVP for these & considering I only sign up for them on *my* computer… Does adobe really need to go to this annoying extent to chase me away?

Yay for greasemonkey.

I found a dreadfully simple greasemonkey script to do the trick, but it wouldn’t really handle a range of forms and didn’t have any validation checks (does the form really exist? does that form element really let you set an attribute?).

The way greasemonkey for firefox is set up it only works on the sites you specify anyways… So if you do want it on certain other sites (like your banking site), don’t add the URL to the list…

Please note that this will go through all forms on the given page & check to see if either the form or any of the form elements have the autocomplete attribute set - if so it should turn the attribute back on.

The name I gave this was Enable Login Forms.

The namespace http://blog.whitelionsoft.com/.

And currently the only page to include this script on is https://www.adobe.com/cfusion/entitlement/index.cfm?e=ca&returnUrl=http://groups.adobe.com/groups/4b06154553/summary.


for ( var i in document.forms ) {
	var frm = document.forms[i];
	if ( frm.autocomplete && frm.setAttribute ) {
		frm.setAttribute( 'autocomplete', 'on' );
	}
	for ( var j in frm.elements ) {
		var ele = frm.elements[j];
		if ( ele.autocomplete && ele.setAttribute ) {
			ele.setAttribute( 'autocomplete', 'on' );
		}
	}
}
  • Share/Save/Bookmark

Sitepoint Helping Victims of Recent Australian Bushfires

Wednesday, February 11th, 2009

Quick details:

  • Offer ends on Friday 13th February (2009).
  • 100% of the proceeds from this sale will be donated to victims of the recent Australian bushfires.
  • Choose any 5 books (in PDF format) and pay $29.95 USD.

A friend of mine just sent me an email today with the subject line of SitePoint 5 for 1 Bushfire Relief Sale and all the body contained was the link http://5for1.aws.sitepoint.com/. Copy/pasting the link into firefox dropped me at a page showing a fireman giving a koala a drink of water - how cute. Scrolling farther down the page past the form for selecting the PDFs you want I found the Why is SitePoint doing this? section and I’m stunned! Wow! Over 170 dead, 5000 now homeless… I hope my friends in Australia are all ok.

(more…)

  • Share/Save/Bookmark

OLPC Update

Saturday, September 13th, 2008

I know there were several people wanting updates on the OLPC.  The GUI is non-standard for a PC of any breed (Mac, Linux, Win) & I had thought of looking to see what other projects were around that would provide an interface I’m more familiar with.

I’m not a large fan of the Red Hat’s (the linux distro that OLPC uses) rpm (yes, I realize yum has come out since I left), but I figured I could mess with whatever for a laptop I’d only be using for taking notes at conferences & such.  I’d still have access to pretty much all the tools & utilities I’m used to.

I ended up with other projects that were more of a priority for me (my mythtv boxes, work, fun…).  And then somebody pointed out Fortune Magazine - With Microsoft, OLPC may finally succeed. While a nifty title I find it on the humorous side.
(more…)

  • Share/Save/Bookmark

One of these things is not like the other…

Tuesday, April 3rd, 2007

Welcome to another edition of “What can go wrong in web design”… or “My Little Opera Rant”.

I dislike table layouts… I’ve said that before right? I didn’t set up the initial page layout on this current project I’m on… I’ve been trying to work around the table design until I can get around to fixing it with something that will work across the board… Somebody designed a great tab system that utilizes nested divs, javascript, & css that displays only certain information at a time - hiding & showing portions of the page depending upon which tab is clicked therefore limiting the scrolling on the page… & it works great… most of the time.

Today I’ve been working on a page that requires both the left column to show up & uses the tab system. Currently I only have information for the form that appears on the first tab so the next 2 tabs simply have a short dummy set. According to “The Style Guide”, the left column (the menu) is supposed to be 130px wide which it is… at least as long as the initial tab is selected. As soon as I click the 2nd or 3rd tabs *in Opera* & only on this particular page so far does it decide that the “width: 130px !important” rule on the left column no longer applies.

The left column suddenly snaps to 222px wide… WTH? The weird thing is this only happens in Opera. I tested Firefox, IE, Opera, & Swift. Oddly enough - Firefox, IE, & Swift all have the same behaviour - the left column stays at 130px no matter which tab I click on… Grrr… WTH is up with Opera?

Initial build I tried this on was Opera v 9.10 build 8679 for WinXP. It’s been bugging me about there being a new version available so I figured I’d download it & see if it fixed this issue… Hmm… now I have Opera v 9.00 build 8502 for WinXP… Does Opera go backwards in it’s build numbers?? Out of curiousity I start typing “opera.com” into opera to see if opera had a url for new downloads - sure enough, browser history had “http://www.opera.com/download/” so I headed there & it says Opera 9.10 is the newest version - um, shouldn’t this say the same as the front page?? So I clicked the download button, install this “new” version of Opera, go to Help->About Opera & guess what version I have! Opera v 9.10 build 8679 for WinXP…. *sigh*

Oh well… I did discover that Opera has a new preview release - 9.20b.

  • Share/Save/Bookmark

Diving into AJAX Tutorials, part 1

Monday, November 13th, 2006

For the past year there’s been alot of AJAX hype & I figured it was about time that I started brushing up on “AJAX”. AJAX was coined in February of 2005 (referenced at wikipedia) by Jesse James Garrett to describe the technologies to a client. As I’ve had alot of free time lately I thought I’d go through several tutorials that I’ve come across….

I haven’t done anything with AJAX in a number of years. Actually the last time I really did much of anything with AJAX was before it was known as AJAX. The interesting thing is how I discovered XMLHTTP (one of the technologies behind AJAX). It was back in the <sarc>”good ol’ days”</sarc> of me programming in Visual Basic. I was trying to find function references and how to do stuff using Microsoft’s MSDN. The navigation system fascinated beyond what it should have & I decided to look at how it worked.

I started off looking for the html or the javascript array that held all the items on the menu. Nothing turned up - in *any* of the html or javascript files. I started digging through the code, reading over it line by line & skipping the easy stuff I already knew (control structures, predefined function calls, etc). At one point I came across this weird XML object that used a URI file reference. That was weird. I had never seen any javascript ever load an external file. I pulled up the entire URL in a new browser window & was presented with an XML tree that had all of the navigation menu items & they were wrapped around weird elements that had what seemed to be non-sensical attributes & attribute values.

I ended up copying all of the code to my computer and started playing around with values. I ended up putting together a small XML file myself and seeing how that worked. It was fascinating, but unfortunately, at that time, only worked on Internet Explorer 5.0 (which was released in 2000). Other browsers had started incorporating it in 2002, but by that time I had already stopped using it as I had started discovering cross-platform/cross-browser bliss.

 

First off I thought I’d go through various issues of .net (dot net magazine) as the articles had looked promising.

The first issue I have with any AJAX coding articles is March 2006, #147 - “AJAX power” & claims to have “fully documented code examples inside” as well as “all your questions answered”. It’s a 7 page article with a bunch of code samples & blah blah text between describing what’s going on. There’s also a bunch of sidebars through out -

  • Find out more about AJAX (urls for 5 AJAX frameworks/engines)
  • Five cool AJAX implementations (doesn’t mention google maps, but they do look good)
  • Expert answers to AJAX questions (see below)
    • do I have to use XML with AJAX [no]
    • could AJAX replace Flash [no, they're different technologies]
    • how is AJAX changing the web [it's giving new responsiveness blah blah blah]
    • why is AJAX becoming so popular when it has been possible for many years [in my opinion they gave a bad answer - it's really because of the acronym & the hype, people have been using it before it was just hidden... not to mention several major companies have picked up on the hype to explain what they were already working on]
    • can AJAX be an enterprise level solution [it can be a part of a solution]
  • Simple AJAX mistakes to avoid
    • breaking the back button
    • no feedback when content is updated
    • unavoidable weaknesses
    • no confirmation
    • spider blocking

 

Here’s a listing of the final versions of the files as well as links to the code for them

 

Ok, so now it’s time to dive into the code samples & see what we have. The first code sample left off the DOCTYPE & html element, but I can understand that as it’s pretty easy to put in myself. There are a bunch more code samples with alot of text detailing what’s going on. Most of what’s listed are functions. Nothing object-oriented, but everything is fairly self explanatory.

Then we reach Creating an object-oriented AJAX engine. All of the code is fairly well done & includes a toString() method, but nowhere does it mention what to name the file this object should be in. I did notice on the next page an HTML fragment that includes “js/Ajax.js”, so I made a js directory and saved this javascript object in there.

Next grouping of code creates an instance of the AJAX object and adds a global onResponse() function which checks the AJAX object’s checkReadyState(...) method. When the browser’s XMLHttpResponse object returns a finished loading state, onResponse() pulls the information out of the retrieved XML & dumps it to the page using .innerHTML attribute of the target element. Okay, so I understand that this is a magazine article & these are code “samples”. However, the novice programmer who’s never used DOM before will think this is standard operating procedure, won’t investigate how he should really program this, & leave it as the code sample says (which could lead to problems down the road with cross-browser issues &/or newer technologies that require DOM compliance…).

The next section is Database interaction with AJAX and PHP. Here’s that HTML fragment I was referring to earlier & it also tells us the name of the PHP file we’re going to be creating. Before we get to the PHP though there’s a bit of SQL that we need to run on the database to create a table to store the information. The bottom of the page has 1 line of PHP, and we flip the page & there’s more PHP. But wait! 1 of the functions refers to this! We’re creating a PHP object… ok, I flip the page back to see if I missed the class name. Nope, only the 1 line of PHP. Was it in the surrounding text? Nope, the previous paragraph & the code sample state -

Now that the table is created we can make the server-side file that will do the direct communication with the MySQL database table. We’ll first need to create a way for connecting to the database, which consists of two methods and a property:

var $table;

public function Post()
{
    require_once('path to.../mysql_connect.php');
    $this-table = 'net_introtoajax';
}

private function dbConnect()
{
    DEFINE ('LINK', mysql_connect (DB_HOST, DB_USER, DB_PASSWORD));
}

.

Okay, well none of that is helpful. I go through all the rest of the code samples in the magazine. The 4th code fragment has what I need, but in a very round about sort of way -

An additional PHP file needs to be created to make a bridge between the AJAX engine and the server-side script that handles the database communication. Below is the code used to create this file:

require_once('../classes/Post.class.php');
$post = new Post();
$post->$method($item);

.

Okay, so now I can add the class code to the “Post.class.php” file (now that we also have a filename). However I notice something very frightening with this last code fragment. It assumes that PHP’s register_globals option is turned on. This can cause all sorts of problems when somebody starts manipulating the URL string to overwrite variables in your application so *most* developers that are aware of it have it turned off (and most web hosting solutions have it turned off as well). The PHP Manual entry on register_globals discusses this issue, but for somebody just glancing over the page, they might not understand what the big deal is. Here’s the code fragment (minus comments) posted under “Example misuse with register_globals = on” -

<?php
if ( authenticated_user() ) {
	$authorized = true;
}

....

if ( $authorized ) {
	include( '/highly/sensitive/data.php' );
}
?>

If register_globals = on and the URL for this page is “http://sample.com/mypage.php“, then all somebody would need to do is go to “http://sample.com/mypage.php?authorized=true” to overwrite the $authorized variable & be able to see the “/highly/sensitive/data.php” contents. Now I hope it becomes clear as to why this is usually turned off.

So, no big deal I’ll just modify the code a little so that it’s a little more appropriate -

My code figure 1 (services/post.php)

<?php
require_once('../classes/Post.class.php');
$post = new Post();
$post->$_REQUEST['method']($_REQUEST['item']);
?>

Okay, back to page 36 where we need to define a bunch of variables for the database. It doesn’t say what file these go in, but I’m making the assumption based on the public function Post() above in the file “classes/Post.class.php” that these go into a file called “mysql_connect.php“. The odd piece here is a the line that states -

$dbc = @mysql_connect (DB_HOST, DB_USER, DB_PASSWORD)
    OR die('Could not connect to MySQL: ' . mysql_error() );

I know exactly what it does. That’s not the issue that I have with it. My problem with it is based upon the fact that it does the exact same thing that the private function dbConnect() in “classes/Post.class.php” above! Only because of the @ it suppresses any errors & the or die(...) segment outputs the mysql_error() if there are any errors… weird, but ok on the suppression & then outputting the error. Duplication of effort where the dbConnect() function is concerned.

Two more code segments flesh out the save($item) & get() methods of the Post class. However, again I have an issue with the code presented. Yes, I know it’s a magazine, this is sample code, & real programmers like me would know how to code this better… but again I screem negligence. Here’s the save($item) method that is presented -

public function save( $item )
{
    $this->dbConnect();
    $query = "INSERT INTO $this->table (item) VALUES ('$item')";
    $result = @mysql_query( $query );
    mysql_close();
    $this->get();
}

.

Okay, so what’s wrong with this you might ask. The problem is the insecurity of the value of $item. This code assumes the whole hearted goodness of the soul that submited $item. The other problem creeps up when somebody even innocently enough adds an apostrophe. Of course this may well depend as to whether yet another PHP variable is turned on or off. PHP has this nifty thing called “Magic Quotes” (magic_quotes_gpc) which, when turned on, automatically escapes single quotes, double quotes, backslashes, and null characters - affecting HTTP Request data (GET, POST, & COOKIE data). So what does this mean?

This means that if someone where to type the following -

I’m able to see “Gone with the Wind” today

Then the variable $item would be equal to -

I\’m able to see \”Gone with the Wind\” today

Unfortunately you can’t always be sure that magic_quotes_gpc = on so you have to escape things the long way. Not only that, but the preferred, more secure way, is to escape a string specifically for the database you’ll be using. Here’s something more along the lines of the way this should have been written -

My code figure 2 (fragment from classes/Post.class.php)


>public function save( $item )
{
$this->dbConnect();
if( get_magic_quotes_gpc() ) {
$item = stripslashes( $item );
}
$item = mysql_real_escape_string( $item );
$query = "INSERT INTO $this->table (item) VALUES ('$item')";
$result = @mysql_query( $query );
mysql_close();
$this->get();
}
The last 2 code segments listed are javascript and are added to the onResponse() function and added to the Ajax class. Now it’s time to load up the page & see how all of this works. Initially there’s nothing there - that’s expected as nothing has been added to the database yet & so there’s no items to list. I type something in & press the “save this item” button & nothing. Okay, that’s weird. I open up Firefox’s error console, hit the clear button to remove everything & start fresh, hit the refresh button. No errors so far. I type something into the text box, hit the “save this item” button again, & again nothing. Not only that, but there aren’t any errors showing up in Firefox’s error console which means the error is not a javascript error. That’s the good news…

I have it load services/post.php & it spits out a blank file. That’s not right… I look again at post.php & notice there’s no default method, so I change the URL to point to services/post.php?method=get. Still a blank page. I put print( 'running method xxxx' ); at the beginning of all the methods in classes/Post.class.php & it still prints out a blank page… Why aren’t I getting any errors? I check my apache vhosts file (for http://patrick.blogdns.org) & notice “php_value display_errors 0” (error reporting has been turned off). So I set up a new apache vhost (http://ajax.patrick.blogdns.org) for my ajax projects & set “php_value display_errors 1“, set the root directory to my ajax projects directory, navigate back to services/post.php?method=get, & get a page with an error. It can’t figure out what I’m trying to do.

Yay for php.net/manual. I pull up the page on Classes and Objects (PHP 5) & using the browsers search functions do a page search for “->$” to see if anybody has posted comments on trying to use a variable to access a class method. Most of the examples show how to access class attributes, but one goes into quite alot of detail.

…..
You can use members of other objects as well:

<?php
print $foo->{$otherObj->var};
print $foo->{$otherObj->func()};
?>

You can use mathods above to access member functions as well:

<?php
print $foo->{'aMemberFunc'}(); // Prints "Inside `aMemberFunc()`"
print $foo->{$foo->aFuncName}(); // Prints "Inside `aMemberFunc()`"
?>

.

Okay, so apparently that’s yet another difference between PHP 5 & prior versions… so I modify services/post.php -

My code figure 3 (services/post.php [final])

<?php
require_once( '../classes/post.class.php' );

if ( !isset( $_REQUEST['method'] ) ) {
	$method = 'get';
}
else {
	$method = @$_REQUEST['method'];
}
$item = @_REQUEST['item'];

$post = new Post();
$post->{ $method }( $item );
?>

I added the check for a method so I could have the code put a default method in there if I forgot while I was testing. I also lower cased the “classes/post.class.php” filename because the capital letter was driving me nuts (I’m lazy & it helps me be lazy when I’m using a console). Technically I didn’t have to create the $method & $item variables, but I wanted the last lines to look like the tutorial as well as keep it open for possible future changes. Not only that, but the PHP compiler is smart enough to not make a copy of a variable until something is actually modified. Until the new (or old) variable is modified, the copy is simply a pointer to the original variable.

Now I reload the services/post.php?method=save&item=item 1 URL &… more errors. Now that it’s actually trying to do something with the instantiated Post object, all the internal errors are now coming to the surface. Okay, let’s start by trying to figure out why it’s defining the LINK constant twice as that may solve some of the other MySQL errors.

private function dbConnect() {
	DEFINE ('LINK', mysql_connect (DB_HOST, DB_USER, DB_PASSWORD));
}

At first I thought there might be several files trying to define ‘LINK‘, but after grep’ing all the files in all of the directories for this small project I only found the 1 file. So the error has to be with that code fragment above. Ah, both the public function save($item) & public function get() call $this->dbConnect(); right off the bat. Not only that, but the last thing that public function save($item) does is call get()! So this only becomes an issue if you’re saving something, but not if you’re trying to retrieve stuff. Best thing to do instead of defining a global variable (since we’re inside an object) is to define a class variable $link & then change the code inside dbConnect() to assign the database resource returned from mysql_connect to it. I’m also going to have it return an error (using or die() even though for a normal project it should return the error, but I’ve wasted enough time on this tutorial already).

My code figure 4 (fragments from classes/post.class.php)

    $link;
    ....
    private function dbConnect() {
        $this->link = mysql_connect( DB_HOST, DB_USER, DB_PASSWORD )
            or die( 'Could not connect to MySQL: ' . mysql_error() );
    }

Now that I have that error taken care of there’s some more errors. Considering how many errors there are I’m going to see if I can deal with just getting a list of items in the database. I pull up phpmyadmin for that server, head into the database and table that were created, & add something. Now I had back to the URL services/post.php?method=get. It’s saying that mysql_fetch_array in get() does not have a valid MySQL result set. Great, so I head to php.net/manual, copy & paste mysql_fetch_array into the search box & press enter which takes me to the mysql_fetch_array page. I dig through that & it seems like everything is ok there. I look through my code some more to find out where $result came from (it’s the result set that PHP is complaining about) -

$result = mysql_db_query (DB_NAME, $query, $this->link);

Best thing to do there is click the link on the php.net manual page for mysql_db_query. I look over everything & everything seems to be ok as far as parameters are concerned. I check my SQL query to see if I’ve made any mistakes there, no problems there either. I scroll down the PHP manual page for mysql_db_query to see the examples & browse over user comments, but before I even get there I see this -

Version Description
4.0.6 This function is deprecated, do not use this function. Use mysql_select_db() and mysql_query() instead.

Beautiful! Checking the PHP release page we find that version 4.0.6 was released 23 June 2001. A tutorial dated March 2006 is using a function that’s been deprecated for over 5 years! Now I can fix that & see what else needs fixing. Now it’s complaining that mysql_query in save($item) doesn’t have a valid resource link. Ok, we just went through this with mysql_db_query so what’s going on? Looking closer at the code I realize that no database has been selected! This entire class needs to be rewritten for it to truly be good, but at this point I just want to get the blasted PHP to work so I can see “the power of AJAX”… wasn’t this article about AJAX & not about PHP?

My code figure 5 (classes/post.class.php [final])

<?php
// pulled from hidden libs directory on server
require_once( 'mysql_connect.php' );
@define( 'NL', "n" );   // my own defined newline character
@define( 'TAB', "t" );  // my own defined tab character

class Post {
    var $table;
    var $link;

    public function Post() {
        $this->table = 'ajax_dotnetintro';
    }

    private function dbConnect() {
//        define( 'LINK', mysql_connect( DB_HOST, DB_USER, DB_PASSWORD ) );
        $this->link = mysql_connect( DB_HOST, DB_USER, DB_PASSWORD )
            or die( 'Could not connect to MySQL: ' . mysql_error() );
    }

    public function get() {
        $this->dbConnect()
        $query = 'SELECT * FROM ' . $this->table . ' ORDER BY id';
//        $result = mysql_db_query( DB_NAME, $query, LINK );
        mysql_select_db( DB_NAME, $this->link )
            or die( 'Could not select MySQL database: ' . mysql_error() );
        $result = mysql_query( $query, $this->link );

        // why would you declare this to be ISO-8859-1 & then in the
        // Content-Type declare it to be UTF-8 ??
//        $xml = '<?xml version="1.0" encoding="ISO-8859-1" ?>';
        $xml = '<?xml version="1.0" encoding="UTF-8" ?>' . NL;
        $xml .= '<list>' . NL;
        while( $row = mysql_fetch_array( $result ) ) {
            $xml .= TAB . '<items>' . NL;
            $xml .= TAB . TAB . '<item><![CDATA[<li>'
                . $row['item'] . '</li>]]></item>' . NL;
            $xml .= TAB . '</items>' . NL;
        }
        $xml .= '</list>';
        mysql_close();

        header( 'Content-Type: application/xml; charset=UTF-8' );
        echo $xml;
    }

    public function save( $item ) {
        $this->dbConnect();
        mysql_select_db( DB_NAME, $this->link );
            or die( 'Could not select MySQL database: ' . mysql_error() );

        if( get_magic_quotes_gpc() ) {
            $item = stripslashes( $item );
        }
        $query = 'INSERT INTO ' . $this->table . ' (item) VALUES (''
            . mysql_real_escape_string( $item ) . '');' ;
        $result = @mysql_query( $query );
        mysql_close();
        $this->get();
    }
}
?>

Ok, now I’m finally getting somewhere. Now I can go back & test the page & see if it’s actually working now. The initial page displays the 1 item I had previously put in the database as well as the other I was using to try to fix the save page (twice as I got it to work & then wanted to make sure it worked). Just to make sure, I type something into the form box & press the “save this item” button & the page blinks as it refreshes the content with the new item at the bottom.

Considering how much work I had to put into the previous files to get this “simple tutorial” to work, not to mention alot of my own modifications to the files presented in the tutorial (to get to meet standards, etc) - I think I should be able to post the other files here as well.

My code figure 6 (index.php [final])

<?php
print( '<?xml version="1.0" encoding="UTF-8"?>' );
$pagetitle = 'Object Return Pattern';
?>

<!DOCTYPE html
    PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title> <?php print( $pagetitle ); ?> </title>
    <script type="text/javascript" src="js/ajax.js"></script>
    <script type="text/javascript" src="js/request.js"></script>
    <script type="text/javascript" >
    	function doLoad() {
			ajax.makeRequest(
				'POST'
				, 'services/post.php?method=get'
				, onResponse
			);
		}
    </script>
</head>

<body onload="javascript:doLoad();">

<ol id="list"></ol>

<br /><br />
<form method="post" action="./" onsubmit="saveNewItem(); return false;" >
<b>Add a new list item:</b>
<br />
<input id='item' />
<br />
<input type="button" name="submit"
    value="save this item"
    onclick="javascript:saveNewItem();"
/>
</form>

</body>
</html>

My code figure 7 (js/ajax.js [final])

function HTTP() {
    this.toString = function() { return 'HTTP'; }

    this.status = function( _status ) {
        switch( _status ) {
            case 200 :
                return "success";
                break;
            case 404 :
                return "File not found.";
                break;
            default:
                return "HTTP Status: " + _status;
        }
    }
}

// requires the js object HTTP
function Ajax() {
    this.toString = function() { return "Ajax"; }
    this.http = new HTTP();

    this.makeRequest = function( _method, _url, _callbackMethod ) {
        // single line if() {}
        this.request = (window.XMLHttpRequest)
            ? new XMLHttpRequest()
            : new ActiveXObject("MSXML2.XMLHTTP")
        ;

        this.request.onreadystatechange = _callbackMethod;
        this.request.open( _method, _url, true );
        this.request.send( _url );
    }

    this.checkReadyState = function( _id, _1, _2, _3 ) {
        switch( this.request.readyState ) {
            case 1 :
                document.getElementById( _id ).innerHTML = _1;
                break;
            case 2 :
                document.getElementById( _id ).innerHTML = _2;
                break;
            case 3 :
                document.getElementById( _id ).innerHTML = _3;
                break;
            case 4 :
                document.getElementById( _id ).innerHTML = '';
                return this.http.status( this.request.status );
        }
    }
}

My code figure 8 (js/request.js [final])

var ajax = new Ajax();
function onResponse() {
    if (
        ajax.checkReadyState(
            'list'
            , 'loading...'
            , 'loading...'
            , 'loading...'
        ) == "success"
    ) {
        if ( ajax.request.responseXML == null ) {
            document.getElementById( 'list' ).innerHTML =
                "There are no list items available.";
        }
        else {
            document.getElementById( 'list' ).innerHTML = '';
            var response = ajax.request.responseXML.documentElement;
            var items = response.getElementsByTagName( 'item' );
            for ( var i = 0; i < items.length; i++ ) {
                document.getElementById( 'list' ).innerHTML +=
                    items[i].firstChild.data;
            }
        }
    }
}

function saveNewItem() {
    var _item = document.getElementById( 'item' ).value;
    ajax.makeRequest(
		'POST'
		, 'services/post.php?method=save&item=' + _item
		, onResponse
    );
}

My code figure 9 (/hidden/mysql_connect.php [final])

<?php
define( 'DB_USER', 'myusername' );
define( 'DB_PASSWORD', 'mypassword' );
define( 'DB_HOST', 'localhost' );
define( 'DB_NAME', 'database' );

/*
$dbc = mysql_connect( DB_HOST, DB_USER, DB_PASSWORD )
	or die( 'Could not connect to MySQL: ' . mysql_error() );
*/
?>

My code figure 10 (mysql.sql [final])

DROP TABLE IF EXISTS `ajax_dotnetintro`;
CREATE TABLE `ajax_dotnetintro` (
    `id` int(11) NOT NULL auto_increment,
    `item` varchar(250) NOT NULL default '',
    PRIMARY KEY (`id`)
) ENGINE=MyISAM COMMENT='.net magazine #147' DEFAULT CHARACTER SET utf8;

Unless I made a typo somewhere while converting the data to display here, all of this code should work. My LAMP setup consists of Debian Linux (Etch - kernel 2.6.8-2-k7, debian 1:3.3.5-12), Apache 2 (2.0.55-4.1), MySQL 5.0 (5.0.24a-9), & PHP 5 (5.1.6-1).

I have to say this was a good exercise in getting PHP files to work… As for the AJAX side of things - there was a couple of useful tidbits, but I’ll go elsewhere for a real set of AJAX tools. No debugging of the javascript files was needed for IE or Firefox… I haven’t bothered testing this in other browsers yet & not sure I’ll ever get around to testing in other browsers.

  • Share/Save/Bookmark

addEventListener/attachEvent & Function References

Wednesday, September 13th, 2006

Craig Fowler stumped me today until he provided a further sampling of his code. Shortly thereafter I realized what the issue was as I’ve run into the same issue in the past (& hopefully this page will prevent me being stumped in the future).

The code he initially presented me with was

<a onclick="obj1.doSomething();"> ...

and he stated he was having issues with using this.someMethod(); inside of obj1… i.e.

var obj1 = new function() {
    this.name = 'Object 1';
 
    this.doSomething = function() {
        this.someMethod(
            'Hello, my name is ' + this.name
        );
    };
 
    this.someMethod = function( text ) {
        alert( text );
    }
};

Granted, you really wouldn’t write code this bad, but we’re just whipping up a quick example to test the problem.

well, putting <a href="#" onclick="obj1.doSomething();"> works just fine… At which point Craig mentioned that that was the end result he was wanting… what he was using to attach it was this snippet from a function -

if(eventElement.addEventListener)
{
    eventElement.addEventListener("click",       subscribers[currentSubscription].shout, false)
}
else if(eventElement.attachEvent)
{
    eventElement.attachEvent(”onclick”,       subscribers[currentSubscription].shout)
}

I had to laugh as soon as I saw it because I remembered doing the same thing. Javascript variables are not really variables… what you create with var a = 1 + 1; is a reference to a protected variable inside the Javascript engine. There are alot of detailed discussions about this elsewhere so I won’t go that route.

Initially looking at the code you may think that the function you’re giving to addEventListener/attachEvent is going to be the code that goes inside the onclick event… i.e.

element.onclick = function() {
    passedFunction();
}

But in reality what is happening is this -

element.onclick = passedFunction;

I don’t know of any good solutions. The solution I had come up with before was to write a proxy function. Craig did the same thing in writing a proxy method into the parent class. A proxy function would be something like the following -

function proxyFunction( evt ) {
    evt = evt || window.event;
    ...code to determine what function *really* needs to be called...
    if ( realFunction ) {
        realFunction();
    }
}

  • Share/Save/Bookmark

Custom JavaScript Events Demonstration

Tuesday, August 29th, 2006

A friend of mine & fellow web geek in the UK, Craig Fowler, has been working on alot of JavaScript lately. He put together a fairly nice library for timed events & such for a visual gallery a while back. Lately he’s been working on a lot of the documentation for it & recently gave me a link to 1 of the demonstration pages -

Custom JavaScript Events Demonstration

  • Share/Save/Bookmark

Internet Explorer Memory Leak

Sunday, January 8th, 2006

Old news, but I seem to need some place to keep track of all the various links for this.

  • Share/Save/Bookmark