Archive for May, 2008

30th May 2008

YouTube API Video Upload

For my latest project I had to work with the new YouTube API. Let us just say the documentation could be improved. It is not that the information is not there, but there is a lack of cross referencing and if you jump to a particular sample, there seems to be the assumption that you have read other parts of the documentation and sometimes they refer to relevant sections, sometimes they do not. And some things are just left out entirely.

For example, the PHP API documentation shows you how to generate the file browse form, but does not mention (aside from a comment in the code about white space in the keywords) the restrictions on the inputs for the form that you would have to submit prior to getting to this point. Some of these include:

  • The < and > characters will cause an error if included in any of the inputs.
  • Submitting a single character keyword will cause an error.
  • The category select form items must have certain values, you can not simply submit the actual text representation of the category.
  • Description is limited to 5000 characters.
  • Total keyword string length can not exceed 120 characters and a single key word can not be over 25 characters.

These can be found elsewhere in the documentation, but again a link to relevant information in the actual PHP example could have saved me a lot of searching and time.

That being said, we did finally get it working (I think).

Posted by Posted by Jeremy Wischusen under Filed under PHP Comments 1 Comment »

26th May 2008

Hey Look, a Mouse.

In one of the books I am reading, Foundation Actionscript 3.0 Animation : Making Things Move! by Keith Peters, he has an example of using trig to make an arrow point at the location of the mouse. I decided to play with this a bit and make an animation where the eyes follow the mouse. I actully ended up adding this to my animation class, so this (after attaching the class via the library linkage):

can be accomplished with:

leftEye.startWatchingMouse();

rightEye.startWatchingMouse();

 

Functions in class:

 

public function startWatchingMouse():void{

stage.addEventListener(MouseEvent.MOUSE_MOVE,watchMouse);

}

public function stopWatchingMouse():void{

stage.removeEventListener(MouseEvent.MOUSE_MOVE,watchMouse);

}

private function watchMouse(event:MouseEvent):void{

var dx:Number = stage.mouseX - this.x;

var dy:Number = stage.mouseY - this.y;

var rad:Number = Math.atan2(dy,dx);

//for some reason the example as written was 90 degrees off, so I added 90 and that fixed it.

this.rotation = rad*180/Math.PI + 90;

}

Edit:

Found a version of the class that has these function in it.

package com.vfd.animation{
/**
* Animation class. Based off of mc_tween2.as project.
* @author Jeremy Wischusen <cortex@visualflowdesigns.com>
*/
import flash.display.Sprite;
import fl.transitions.Tween;
import fl.motion.Color;
import flash.geom.ColorTransform;
import fl.transitions.TweenEvent;
import flash.events.Event;
import flash.events.MouseEvent;
public class AnimatedClip extends Sprite {
private var originalX:Number;
private var originalY:Number;
private var xTween:Tween;
private var yTween:Tween;
private var alphaTween:Tween;
private var rotationTween:Tween;
private var widthTween:Tween;
private var heightTween:Tween;
private var eventTween:Tween;
private var tweenArray:Array;
private var colorTween:Tween;
private var colorTrans:ColorTransform;
private var tweenToColor:Number;
private var lastColor:Number;
private var timerClip:Sprite;
private var orbitAngle:Number = 0;
private var _orbitVelocity:Number = .5;
private var _orbitY:Number = stage.stageHeight/2;
private var _orbitX:Number = stage.stageWidth/2;
private var _orbitDistance:Number;

public function AnimatedClip() {
this.originalX = this.x;
this.originalY = this.y;
this.xTween = new Tween(this, "x", null, this.x, this.x, 1, true);
this.yTween = new Tween(this, "y", null, this.y, this.y, 1, true);
this.alphaTween = new Tween(this, "alpha", null, this.alpha, this.alpha, 1, true);
this.rotationTween = new Tween(this, "rotation", null, this.rotation, this.rotation, 1, true);
this.widthTween = new Tween(this, "width", null, this.width, this.width, 1, true);
this.heightTween = new Tween(this, "height", null, this.height, this.height, 1, true);
this.timerClip = new Sprite();
this.colorTween = new Tween(this.timerClip,'alpha',null,0,1,1,true);
this.colorTween.stop();
this.tweenArray = new Array(this.xTween, this.yTween, this.alphaTween, this.rotationTween, this.widthTween, this.heightTween,this.colorTween);
this.colorTrans = this.transform.colorTransform;
this._orbitDistance = this.width*2;
this.colorTween.addEventListener(TweenEvent.MOTION_CHANGE, updateColor);

}
public function resetPosition():void {
this.x = this.originalX;
this.y = this.originalY;
}
public function moveToPoint(x:Number, y:Number,duration:Number = 0, loop:Boolean = false):void {
this.xTween.finish = x;
this.xTween.duration = duration;
this.xTween.looping = loop;
this.yTween.finish = y;
this.yTween.duration = duration;
this.yTween.looping = loop;
this.xTween.start();
this.yTween.start();
}
public function fadeTo(val:Number =0, duration:Number = 0, loop:Boolean = false):void {
this.alphaTween.finish = val;
this.alphaTween.duration = duration;
this.alphaTween.looping=loop;
this.alphaTween.start();
}
public function sizeTo(w:Number, h:Number, duration:Number=0, loop:Boolean = false):void {
this.widthTween.finish=w;
this.widthTween.looping = loop;
this.widthTween.duration = duration;
this.heightTween.finish = h;
this.heightTween.looping = loop;
this.heightTween.duration = duration;
this.widthTween.start();
this.heightTween.start();

}
public function widthTo(width:Number, duration:Number, loop:Boolean = false):void {
this.widthTween.finish =width;
this.widthTween.looping = loop;
this.widthTween.duration = duration;
this.widthTween.start();
}
public function heightTo(height:Number, duration:Number, loop:Boolean = false):void {
this.heightTween.finish =height;
this.heightTween.looping = loop;
this.heightTween.duration = duration;
this.heightTween.start();
}
public function spinTo(rot:Number= 0, duration:Number = 0, loop:Boolean = false):void {
this.rotationTween.finish=rot;
this.rotationTween.duration = duration;
this.rotationTween.looping = loop;
this.rotationTween.start();
}
public function xTo(x:Number, duration:Number = 0, loop:Boolean = false):void {
this.xTween.finish = x;
this.xTween.duration = duration;
this.xTween.looping = loop;
this.xTween.start();
}
public function yTo(y:Number, duration:Number = 0, loop:Boolean = false):void {
this.yTween.finish = y;
this.yTween.duration = duration;
this.yTween.looping = loop;
this.yTween.start();
}
public function set easing(ease:Function):void {
for (var tw in this.tweenArray) {
tweenArray[tw].func = ease;
}
}
public function colorTo(toColor:Number, duration:Number):void {
this.lastColor = this.transform.colorTransform.color;
this.tweenToColor = toColor;
this.colorTween.duration = duration;
this.colorTween.start();
}
private function updateColor(event:TweenEvent):void {
this.colorTrans.color = Color.interpolateColor(this.lastColor, this.tweenToColor,event.position);
updateColorTransform();
}
public function set currentColor(clr:Number) {
this.lastColor = clr;
this.colorTrans.color= clr;
updateColorTransform();

}
public function startOrbit():void {
this.addEventListener(Event.ENTER_FRAME,orbit);
}
public function stopOrbit():void {
this.removeEventListener(Event.ENTER_FRAME,orbit);
this.orbitAngle = 0;
}
private function orbit(event:Event) {
this.y = this._orbitY + Math.sin(this.orbitAngle)*this._orbitDistance;
this.x = this._orbitX + Math.cos(this.orbitAngle)*this._orbitDistance;
this.orbitAngle += this._orbitVelocity;
}
public function startWatchingMouse():void{
stage.addEventListener(MouseEvent.MOUSE_MOVE,watchMouse);
}
public function stopWatchingMouse():void{
stage.removeEventListener(MouseEvent.MOUSE_MOVE,watchMouse);
}
private function watchMouse(event:MouseEvent):void{
var dx:Number = stage.mouseX - this.x;
var dy:Number = stage.mouseY - this.y;
var rad:Number = Math.atan2(dy,dx);
this.rotation = rad*180/Math.PI + 90;
}
public function set yEasing(ease:Function) {
this.yTween.func = ease;
}
public function set xEasing(ease:Function) {
this.xTween.func = ease;
}
public function set heightEasing(ease:Function) {
this.heightTween.func = ease;
}
public function set widthEasing(ease:Function) {
this.widthTween.func = ease;
}
public function set alphaEasing(ease:Function) {
this.alphaTween.func = ease;
}
public function set rotationEasing(ease:Function) {
this.rotationTween.func = ease;
}
public function set orbitVelocity(velocity:Number) {
this._orbitVelocity = velocity;
}
public function set orbitY(y:Number) {
this._orbitY = y;
}
public function set orbitX(x:Number) {
this._orbitX = x;
}
public function set orbitDistance(distance:Number) {
this._orbitDistance = distance;
}
public function get currentColor():Number {
return this.lastColor;
}
private function updateColorTransform() {
this.transform.colorTransform = this.colorTrans;
}
}
}

Posted by Posted by Jeremy Wischusen under Filed under ActionScript 3, OOP Comments 2 Comments »

25th May 2008

Flex YouTube Video Search

Since I had such a fun time with the Truveo video search, I decided to do the same type of thing with YouTube. I was originally going to have it play the video, but as it turns out for some reason when loading a YouTube player into a SWFLoader, it only works the first time and the fixes I found are a little more than I can to put into something that is basically just an experiment.

Posted by Posted by Jeremy Wischusen under Filed under ActionScript 3, Flex Comments No Comments »

24th May 2008

Using JavaScript Regular Expressions for Ajax Navigation

When I originally designed my site, I decided that I would make the navigation systems Ajax (partially because I wanted to expand my skills, partially to decrease load times, and partially because I thought I was being clever). So I got the basic nav systems working and I was all happy with myself right up until the first time I tried to provide direct link to one of my samples. As usual, I am not as clever as I first thought.

A direct link to the samples (or any other page for that matter) would load the page outside of the context of the nav system and site layout, which defeated the point of the nav systems and looked like crap (not that it is visually stunning within context, but even more so than normal).

I decided this was no good and started formulating ideas of how I could make particular locations within my site directly accessible without having to scrap my existing navigation system.

Upon reflection realized that one of the things jQuery makes pretty easy is triggering events on objects, such as clicks. So if I could identify the main and sub section I want to go to, I could trigger the click events for the appropriate links and end up where I wanted to be.

Now I just need to figure out how to pass that information. Fortunately, the other day there was a discussion on Flashkit about a URL system called SWFAddress. Basically, this system uses the named anchor system with the # sign so that you can change the last part of the URl string with out the browser actually taking you to another location. This leaves you with a parseable URL.

So now I had a way to get to my desired location (trigger click event), and a method of passing the data (the # url trick) I needed to be able to distinguish which path of the url referred to the main section and which referred to the sub. I decided to go with the following syntax:

http://www.visualflowdesigns.com/#main:main_page.html#sub:sub_page.html

All that was left is to parse the URL and trigger the click events for the links:

Main Section:

var mainSection = window.location.href.match(/#main:\w+\.html?/)
if(mainSection){
//perform string replacements to convert the id to jQuery syntax and to escape special jQuery caharcters
var goto = mainSection.toString().replace(/main:/,'').replace(/\./,'\\.');
$(goto).click()
}

Sub Section:

var sample = window.location.href.match(/#sub:\w+\.html?/)
if(sample){
//perform string replacements to convert the id to jQuery syntax and to escape special jQuery characters
var goto = sample.toString().replace(/sub:/,'').replace(/\./,'\\.');
$(goto).click()
}

The nice part about this is that since I am triggering the click events, my menus update themselves just as if the user had clicked on them.

The current system solves my immediate problem of not being able to provide direct links to my samples, but even as I wrote this I noticed that I am locking myself into HTML pages with my regular expression. However, now that I have the basic system working, I can play with and tweak it as needed.

As always Ideas and comments welcome.

Posted by Posted by Jeremy Wischusen under Filed under DHTML, jQuery Comments No Comments »

21st May 2008

Flex Truveo Video Search

A few weeks ago someone contacted me about writing about the new APIs that AOL has made available. While looking at the AOL dev site I came accross the Truveo API and decided I would try creating a search application in Flex.

Posted by Posted by Jeremy Wischusen under Filed under ActionScript 3, Flex Comments No Comments »

15th May 2008

Flash Player 10 Available on Labs

Not much else to say on this one. There was a post on Flaskit board about this, so I thought I would put it here as well.

http://www.adobe.com/go/astro

Posted by Posted by Jeremy Wischusen under Filed under Flash Comments No Comments »

14th May 2008

AS 3 Animated Clip Class

So recently I finished (as in have something usable, they’re never finished) an AS3 animation class.

Basically I client of mine had me use mc_tween.as for a few projects and I decide to have a go at creating something similar in AS3 (from what I have read on the author’s site, he to is working on an AS3 version).

If you want to check out the class, you can find it on google code. Again, all of this stuff is a work in progress, so bugs are par for the course.

Here is a quick sample of how it can be used. The following example is created using this code:

//ball is a movie clip whose class I have set in the linkage dialog to com.vfd.animation.AnimatedClip;
import fl.transitions.easing.*
ball.easing = Bounce.easeInOut
ball.fadeTo(0,2, true);
ball.sizeTo(10,10, 2, true);
ball.spinTo(90, 2, true)
ball.orbitDistance = 50;
ball.startOrbit();

UPDATE:

Also started an AS 2 version. In the same code repository on google code.

Posted by Posted by Jeremy Wischusen under Filed under ActionScript 3, OOP, Open Source Projects Comments No Comments »

13th May 2008

Retaining a Dom Object Across Ajax Calls (In Order No Less)

I have been working on a project that displays a list of items that a user can take one of several actions on. Taking an action would change the display state and give the user a message that their action had been successfully completed, or that something went wrong. The user could then close the item and in doing so, update the list of items via an Ajax call.

This worked well enough, however, one of the project managers decided that they did not like the fact that the user had to take an action to update the list by closing one of the items they had acted upon, nor the fact that if they took actions on multiple items, they would have multiple feedback message displayed until they closed one of them triggering the update. So I ended up with the following requests:

  • Taking an action on another item in the list should close any other items that have previously had an action take on it.
  • If the user has less than 10 items in their cue, perform an Ajax call to see if they have any new items that have arrived each time they take an action.
  • The last message they received for the last item they took action on should remain across the Ajax calls.
  • If the item they took action on was in the middle of the list, then it should be in the same spot in the new list.

Now the response I was getting from the Ajax call was being sent into the div that contained the list of items. In other words, the entire list was being replaced. So now I had to figure out how to determine the last item an action was taken on, save it and insert it back into the same location in a new list of items that was replacing the old list.

jQuery to the rescue.

In order to display on the last item an action was taken on, I used a two step process. I used a class to identify items that had actions taken on them called actionTaken. So when an action is taken on an item, I remove all elements with that class and then assign that class to the item the action was just taken on. Since I hide all of the items before assigning the class to the last item I took action on, it essentially hides all of them except for the one I just took action on. This basically looks like:

$('.actionTaken').remove()
$('#listItem'+id).addClass('actionTaken'); .

Id in this case is a unique identifier generated in PHP and assigned to the div. So that takes care of only showing the last item a user took action on. This also works in the first case where there is no previous item since the call to remove simply does not find any element and does nothing.

Now I need to figure out how to keep that last item across Ajax calls. Since I now knew that only the last item they had taken action on would be displayed, and that item would have a particular class assigned to it, I could not retrieve that DOM node as follows:

var lastItem = $('.actionTaken').parent().html();

Next I need to determine where this item is located in the list. I do this by retrieving the ID of the item that follows the item of interest in the list.

var insertBefore = $('.actionTaken').parents('tr').next().attr('id');

Now that I have the last item and I know the item that follows it, I take the data I got back from the Ajax call and add it to the DOM.

$('#itemListDiv').html(str);

Finding the item that follows the items we are trying to retain works in most cases except one: if the item in question happens to have been at the end of the list. So I needed to determine if we had found an item following the item being retained. If we did, I insert it back into the DOM structure at the appropriate location (before the item it appeared before in the previous list), otherwise, I just throw it back onto the end of the list.

if (insertBefore ){
$('#itemTable #' +insertBefore ).before('<tr><td>' +lastItem + '</td></tr>');
}else{
$('#itemTable').append('<tr><td>' +lastItem + '</td></tr>');
}
}

There is more code to this system, but as far as the problems I initially outlined, that’s the relevant code. I now had a system that would only display the last item the user took action on and that item would be retained across Ajax callas and appear in the list at the same location.

Posted by Posted by Jeremy Wischusen under Filed under CSS, DHTML, jQuery Comments No Comments »

08th May 2008

High Performance Web Sites

One of the books I picked up recently is

High Performance Web Sites : Essential Knowledge for Frontend Engineers by Steve Souders

Despite its small size, it is full of interesting suggestions for making web sites load faster. On page 5 he puts forth the Performance Golden Rule:

“Only 10 to 20 % of the end user response time is spent downloading the HTML document. The other  80 to 90 %  is spent downloading  all of the components for the page.”

Now most of the discussions I have had around the office center around how to optimize the back end (e.g., improving query performance, what PHP functions are faster than others). This book only mentions these subjects in regards to how over emphasized they tend to be (not implying they are not important, but tend to over shadow front end optimization).

The book goes on to outline 14 rules. They are as follows in order of importance:

  1. Make fewer HTTP requests.
  2. Use a content delivery network.
  3. Add an expires header.
  4. Gzip contents.
  5. Put style sheets at the top.
  6. Put scripts at the bottom.
  7. Avoid CSS expressions.
  8. Make JavaScript and CSS external.
  9. Reduce DNS lookups.
  10. Minify JavaScript.
  11. Avoid Redirects.
  12. Remove duplicate scripts.
  13. Configure Etags.
  14. Make Ajax cacheable.

If you are interested in the explanations as to why these dramatically decrease page load time, I would highly recommend picking the book up.

And in case you are wondering why you should listen to this guy at all, he is the chief performance officer at Yahoo.

Posted by Posted by Jeremy Wischusen under Filed under Performance Comments No Comments »

06th May 2008

Setting a Character Limit for TextArea with jQuery

So today I was asked to impose a character limit on a messaging system I have been working on. The message in question is input into a textarea in a form. So I vaguely remember something about a max character property and proceed to do a google search for character limit textarea. Well as it turns out, the character limit I was thinking of only applies to inputs of type text. What I found in my search results were various permutation of using JavaScript to impose a limit. Since I am now a big fan of jQuery, I decided to implement it using that.

Here is what I ended up doing.

  1. Assign a common class to the message text areas. Using a class as opposed to an ID allows us to apply this to multiple text areas on the same page, should the need arise.
  2. In the script file for the page bind a function to check the length of the text in the text area as follows:
    $(document).ready(initPage);
    function initPage(){
    $('.myTextAreaClass').keypress(limitMessageLength)
    }
  3. Create a function to limit the number of characters:
    function limitMessageLength(){
    var text = $(this).val();
    if (text.length > 100) {
    $(this).val(text.substr(0, 100));
    }
    }

Now any page that includes this script file and has forms with text areas with that class, will trigger the limiting function.

I have noticed some weirdness where when you reach the character limit, the last character changes to the last character you typed, but over all, seems to get the job done.

Posted by Posted by Jeremy Wischusen under Filed under DHTML Comments No Comments »