jQuery Growl 1.0.0-b3 Released
I just released the latest beta of jQuery Growl, adding in the new noticeDisplay/noticeRemove features. I updated the jQuery Plugin Project page and uploaded the latest ‘beta 3′ to release it to the general public.
This release is rather minor, and only really provides a small bug fix and introduces the ability to override noticeDisplay() so that you can have your own custom animations and effects to display your notice.
Enjoy and let me know if you experience any problems with it, or have any updates that are within the ‘growl scope’ (I’ve been asked by a few people to make updates/changes to the Growl Plugin which I decided not to implement due to the lack of ‘Growlness’ in the requests. Please refer to the official Growl homepage and experiment with the actual application before asking for feature updates, thanks.).
CakePHP 1.2 and JSON
While working on BartenderDB.com I decided to try to make the ‘data entry’ as ‘fluid’ as possible, meaning … lots and lots and LOTS of AJAX. Using jQuery of course.
While looking for some nice Cake 1.2 JSON information, I ran across an interesting post on Pagebakers called Using JSON in CakePHP 1.2. I gave it a quick read (actually, I skimmed it for code snippets and just rolled my own from the ‘general idea’) and it helped out tremendously. I was up and running with JSON in under 5 minutes. Great resource, and kudo’s to the poster.
After setting up my JSON Views, I realized that Cake was still in ‘debug’ mode — so I modified my views/layouts/json/default.ctp and simply added a Configure::write(’debug’,0); to it … and viola, problem solved, all my JSON requests were free of Cake’s added dev/staging information.
Javascript Calculator
While working on a side project, for which I found a small amount of time to work on. I created this rather simple and basic calculator, made with jQuery (Of course).
You can view the calculator here: jQuery Calculator
It was rather simple to build, and I don't even think that the source is really worth describing or going into detail with. The only thing I think is worth mentioning is the use of the 'eval' function, which allowed me to dynamically create javascript on the fly and take the result of it.
In this case, I passed in the Left and Right values along with the operator and simply stored the output. For example, if you typed in "55", hit "+" and then entered "100". I simply call:
-
var result = eval('55' + '+' + '100');
Which resulted in the numeric value of 155, of course.
IE7’s Implicit CSS Quirks
If your developing an absolutely positioned site layout, and wondering why IE always seems to be a bit 'off', it might be because of the odd implicit CSS values that it has. For example, the BODY element has an implied 2px (medium) thick border, that is set to the 'inset' style.
This is done, I guess, to give the page a visually appealing look inside the IE container ... but is obnoxious as it has to be overriden in CSS explicitly and if you forget ... your layouts are all off.
I wrote a rather simple QUnit test, as an exploration of the QUnit framework and found that my tests kept failing in IE due to a 2px difference in absolutely positioned elements offsets -- which, should always be the top/left values when the element is explicitly positioned absolutely (top and left are both set, no inheritence).
To determine this, my test utilized the isObj() function of QUnit, and looked similar to this:
-
module("Absolute Position");
-
test("Top Left (0,0)", function() {
-
$('#testDiv').css({position:'absolute', top: 0, left: 0});
-
var expected = {top: 0, left: 0};
-
ok(true, $('#testDiv').offset().left + ', ' + $('#testDiv').offset().top);
-
isObj(expected, $('#testDiv').offset(), "Element should be {left: 0, top: 0}");
-
});
The first assertion, 'ok', was done simply so I could see the top/left values in the event of a test failure. I think a nice addition to the QUnit framework would be a 'pretty print' function for objects so you could see exactly why a test failed when the expected result is a simple object (no functions attached to it).
QUnit for jQuery
I've been intriqued by the concept of Unit Testing for quite some time, though, honestly, have never really looked much into it. A coworker sent me a link to a LosTechies.com blog and now I'm even more intriqued ... Unit Testing specifically for my jQuery, hrm .... now that sounds interesting.
I'll be exploring this on my free time for sure.
Optimizing Web-Forms with jQuery
Ever look at some of your forms and think, wow, that's repeatitive. Yep, you know those multi-level search forms, or tabbed interfaces with repeated drop down values? Those are the ones.
Ever wonder how you could optimize them for the client and reduce some of the overhead? For example, say you've got a site that has multiple categories, and for each category you can search by State, Region and some other 'Long List' of filterable data (model, manufacturer, artist, author, etc) -- ever think it was a good idea to create a tabbed interface to help break it out ... since Searching by Artist really has different fields then searching by Author ... one's a song, the others a book ... they have similar qualities, but not the same so the form differs for each.
Say for example, you have 5 forms on your 'search page' and each form is hidden behind a 'tabbed user interface' (toggled display attributes with a little bit of simple javascript), now, on each of these forms you have the same select/option drop-down with the same values. The only thing that differs, or may not, is the elements ID attribute.
Ever looked at how much space was consumed by a simple US State drop-down? Nearly 4kb of data is inside the <select /> tag <option value="xxxxx">Alabama</option> ... 50+ times (especially if you include regions and sub-regions in the list). Now, you've got this same drop down in 5 places on the page -- thats 4kb times 5, nearly 20kb of bandwidth required by the end user to download your page now.
Be nice to trim that down to a simple 5kb, wouldn't it?
With jQuery, we can ... and here's how:
-
<select id="myFirstStateDropDown">
-
<option value="1">Alabama</option>
-
<option value="2">Alaska</option>
-
....
-
<option value="50">Hawaii</option>
-
</select>
We start with this, and we populate all of our values into it -- pretty simple, your site probably already has this going on -- multiple times (gotta love CTRL-C/CTRL-V action, eh?).
Now, we add a little bit of jQuery:
-
$(document).ready(function() {
-
var replicated = $('select.replicated');
-
for(var x = 0; x <replicated.length; x++) {
-
var rel = $(replicated[x]).attr('rel');
-
var src = $('#' + rel);
-
var dst = $(replicated[x]);
-
dst.empty();
-
dst.append($('option', src).clone());
-
}
-
});
Wait ... uhm, we're missing something ... the destination place holders, so let's add some in:
-
<select id="mySecondDropDown" rel="myFirstStateDropDown" class="replicated">
-
<option value="">-- Any --</option>
-
</select>
Repeat the above as many times as you need too, in as many places as you need, save and load up your page ... watch as all the 'replicated' drop downs automatically populate themselves using the first drop downs values ...
Pure magic, really.
Ok, it's not magic ... it's jQuery ... and even then, it's really just as simple with pure JavaScript. If your site does not already include jQuery in it's list of requirements, then simply swap out the $() selector stuff with document.getElementById calls, and then write a simple 'clone' function (I'll probably write something about doing it this way later on ... right now, I'm hungry.)
jQuery 1.0.4 and jQuery Growl
Per request, I attempted to back-port jQuery Growl to support jQuery 1.0.4 -- which is the default version of jQuery shipped with Drupal 5.x (5.4 was the target drupal version). Unfortunately, after digging around quite a bit, I realized that jQuery 1.0.4 had so many bugs in it that it was impossible for 'me' to back-port my Growl implementation without rewriting it from the ground up and essentially relearning jQuery all over again (ignoring everything I know of the 1.2.x releases, and learning 'old school' jQuery methods).
This turned out to be so problematic, that I eventually gave up after a few hours. Some of the things I noticed in jQuery 1.0.4 was the lack of variable checking, ensuring that the variable had a value before attempting to access items within it. Others were the lack of support for certain CSS properties, etc.
I did, at one point, get a copy of jQuery Growl working with 1.0.4 locally but once I deployed it to my server as version 1.0.0-b2 and tested it on my remote server with the 'fortune.php' implementation, it failed to work properly and I was unable to determine the cause of the problem.
So, with that said ... I'm so glad that jQuery has matured to the point that it is at now and I hope that it continues to get better and better. I don't think I would be so interested in jQuery if I had started using it prior to the 1.2.x releases -- buggy frameworks tend to make me walk away, run away in fear in some cases.
The Making of Evil Clutches, Javascript version.
This is a quick and dirty walk-thru on how I put together the 'Evil Clutches' javascript demo. First of all, I bought the book 'The Game Makers Apprentice' and built the first game, in Chapter 2. It's called "Evil Clutches", without the "Javascript". This was a fairly easy game to build with Game Maker and so, after building it and playing it a few times, I took the art resources and modified them a little (made them PNG instead of GIF, removed the animation frames, etc).
After doing this, I started building out my CSS Stylesheet to describe my resources, each resource has it's own style and all my 'objects' use the 'object' class (which simply says "position: absolute".
So, here's a quick example of some of the CSS:
-
.demon {
-
width: 130px;
-
height: 140px;
-
background-image: url(Demon.png);
-
}
My 'game' area is defined as a static object, like so:
-
#game {
-
position: relative;
-
margin: 0pt auto;
-
width: 640px;
-
height: 480px;
-
border: 1px solid #fff;
-
background-image: url(Background.jpg);
-
overflow: hidden;
-
}
Note the 'overflow: hidden' to prevent objects from 'bleeding' out of my game area, also note the 'position: relative' which allows my absolutely positioned children to be offset by the game board. So '0,0' for a child of 'game' is the top-left of the 'game' element, not the document/window.
Now, I have two other static objects, my Dragon and my Boss, and these were defined as such:
-
#dragon {
-
width: 135px;
-
height: 150px;
-
background-image: url(Dragon.png);
-
top: 0px;
-
left: 10px;
-
z-index: 20;
-
}
-
-
#boss {
-
width: 135px;
-
height: 165px;
-
background-image: url(Boss.png);
-
top: 0px;
-
right: 10px;
-
z-index: 20;
-
}
I added a z-index to these, to ensure they were placed over top of any of my dynamic objects (Demons, Babies and Fireballs), which was done to prevent any 'bleeding' overlap when the objects collide.
After I created this style sheet, I started writing some code. First off, I created the 'JSGameLib' side-by-side with this demo, but for the purposes of this walk-thru, we'll skip the 'making of' for JSGameLib.
I added my script references, which included jQuery 1.2.3, jQuery Growl, and JSGameLib. I then added a reference to 'index.js', which was just a simple script file i created to hold my games code.
So, let's take a look at 'index.js'.
At the very top, I define a bunch of global variables, this is to help reduce some of the strain on the browser while executing the code repeatedly. Three of the most common things I reference are the Game area, the Dragon and the Boss. As these are static objects that always exist, and only have one instance of each, I simply store a reference to a jQuery object that points to them.
In my $(document).ready() I set some of the jQuery Growl settings, to make it look a little nicer, as well as add the 'object' class to all of my 'game' children (I did this so I didn't have to remember to do it when I laid out the Markup on the page).
One of the children in my 'game' area is the 'overlay', which basically hides my screen and provides basic user instructions. To begin the game, we click this area, so I attached a simple jQuery click handler and it simply calls "gameStart". I also added a click handler to my 'Stop Game' button, which calls "gameOver".
"gameStart" is pretty simple, it initializes all my global variables to there default values and stores a few pre-calculated values onto my static Dragon, Boss and Game objects. Namely the 'h' and 'w' properties, so I don't have to calculate these every time i need to know what they are -- this also allows me to quickly resize my artwork and change my game area without having to change -ANY- of my code.
The game 'starts' by calling the 'bossDown' function, which basically just animates my 'boss' object by making it move to the bottom of the screen, this 'animate' function has a complete handler, which calls 'bossUp' (take a wild guess what 'bossUp' does?). These are basic jQuery methods, and you can review the docs for the 'animate' function of a jQuery object. The 'unique' thing is the simple 'complete' handler, which generates a simple 'loop' which makes my boss object go 'up and down' repeatedly.
I make a call to 'dragon.controlled()', and 'controlled' is a function available in JSGameLib and I pass in some basic options, enabling support for the UP and DOWN (Arrow Keys and WASD style) as well as a 'speed' and 'duration' override. For more details, please take a look at the JSGameLib documentation. Following this, I add a 'keypress' handler and look for 'space' (charCode: 32). If you press 'space', I call the 'fireball' function. This function simply creates a new DIV element with a class of 'fireball object' and then sets the Top and Left CSS attributes to that of the dragons' current position. I also set 'display: none' to make the object hidden initially, and then call 'animate' with an 'opacity: show' to make the fireball fade in quickly. While it is fading in it also begins to start moving by setting 'queue: false' in the 'animate' options. I simply tell the fireball to move '+=675px' over the course of 2000 milliseconds. Once 'complete', I remove the fireball.
Pretty straight forward so far, eh?
I'm out of time for now, but will finish this up later on -- hopefully adding some more detail to what's written already.
Javascript Game Library
I am currently in the process of building a 'Javascript Game Library', which is being implemented as a simple jQuery plugin. So, with that said, it requires jQuery (1.2.3 to be exact). Currently, it supports very little, but with the limited functionality it has right now, it's capable of doing quite a bit of interesting things.
You can view a demo of the 'collision detection' and 'keyboard movement' here:
http://projects.zoulcreations.com/jquery/JSGameLib/
Or, better yet, you can view a 'game' written with the library here:
http://projects.zoulcreations.com/games/JSEvilClutches/
Anyone familiar with 'Game Maker' will most likely notice this game as 'Evil Clutches' from 'The Game Makers Apprentice'.
Some small notes on the Demo Game:
It does not seem to work in anything other then Firefox currently, and as I do not have a Mac to test with diligently, I will most likely not have Safari support any time soon -- JSGameLib seems to work fine in IE, Safari and Firefox ... however, the Demo Game has some problems (objects spawn in the wrong place) which is either related to a CSS issue and Firefox is just too forgiving, or it's related to an issue with jQuery not having access to certain pieces of information at the time the values are being set. Either way, I intend to make it support Safari for Mac and hopefully IE for Windows as well.
jQuery Morph Preview
I was looking through some of the features offered by MooTools, and came across the Fx.Morph demo. I liked the look and feel of this and have seen it before in the past. However, in the past, I assumed it worked much like the common jQuery.animate(css,options) function. I actually looked at the demo and realized, it was morphing from one named style to another, without passing the actual style information into the 'animation', just the 'morph to' CSS class.
I did a bit of research, and found out that it's pretty easy to retrieve the current stylesheets and CSS Rules in Firefox (Safari and Opera also support this, to my knowledge) and so, began to create a simple 'jQuery.Morph' plugin for myself. I threw up a quick demo page, that is actually just a pseudo-recreation of the MooTools Fx.Morph demo (same Markup, same Style). You can compare the two and see some minor differences ... namely the background color not fading in as smoothly as it does with MooTools.
I hope to be able to finish this up at some point and release it to the general public.
You can view the preview here:
http://projects.zoulcreations.com/jquery/morph
UPDATE: I looked into the IE Support a bit more and figured out how to use document.styleSheets instead of the original method, and jquery.morph.js has been updated to reflect that. However, there seems to be a small bug in jQuery 1.2.3 (maybe not so small? :P) that is throwing errors in IE when you try to animate things like 'color' and 'overflow' (basically, anything that does not map back to a 'unitable numeric').
-
fx.elem.style[ fx.prop ] = fx.now + fx.unit;
This is the offending code, in the _default for the step. I didn't look through jQuery enough to figure it out (thousands of lines of code without a 'goto definition' isn't fun to debug) but I believe this should be considered a bug ... especially since the code does not validate either before calling this _default function or in the _default function. As it's a "default" handler, it should assume all possible types of values and gracefully exit if it's "no good". Which, it appears to do in Firefox, but that could just be because Firefox ignores when you try to set a style to an invalid value, and IE is simply saying "Hey, dummy, you cant do that" (forgiveness is a nice thing, you know?).


