Posts Tagged ‘javascript’

Posted by admin at 5 August 2009

Category: programming

Tags: ,

If you are not a seasoned Javascript developer (like myself), and you start writing Javascript classes which include jQuery event bindings, you may become stumped on the issue I am about to describe. On the contrary you are most likely more intelligent than I and realize that what you are trying to do is wrong and you consult the jQuery documentation to find the answer within the first 2 minutes of stumbling upon this problem.

Anyways, the issue at hand is setting up event bindings via jQuery inside of a class. This is easier explained with a simple code example. Take the following class:

function Page()
{
	var msg  = 'weeeeeeee';

	this.bindElements = function(elementOne, elementTwo)
	{
		$(elementOne).click(function() {
			this.elementOneStuff('yoyo');
		});
		$(elementTwo).click(this.elementTwoStuff);
	}

	this.elementOneStuff = function(a)
	{
		alert(a);
	}

	this.elementTwoStuff = function()
	{
		alert(this.msg);
	}
}

var p = new Page();
p.bindElements('#btnOne', '#btnTwo');

When you instantiate a new Page object and invoke the bindElements method you get barked at:

this.elementOneStuff() is not a function.

My initial reaction was that it was a scoping issue with my privileged class methods. After changing the architecture of my class to use public methods the same issue was there.

Solution / Answer

The this keyword that is being used in both of the callbacks will refer to the DOM element that dispatched the event…. not an instance of the Page Class. This is in fact the correct behavior as it will almost always be what is desired.

jQuery.bind( type, [data], fn ) to the rescue! Straight from the jQuery documentation:

data (Optional) Object
Additional data passed to the event handler as event.data

We can simply pass an object as the data parameter to the bind method and then invoke our class methods through event.data. So the updated, correct code would be:

function Page()
{
	var msg  = 'weeeeeeee';

	this.bindElements = function(elementOne, elementTwo)
	{
		$(elementOne).bind('click', this, function(evt) {
			evt.data.elementOneStuff('yoyo');
		});
		$(elementTwo).bind('click', this, function(evt) {
			evt.data.elementTwoStuff();
		});
	}

	this.elementOneStuff = function(a)
	{
		alert(a);
	}

	this.elementTwoStuff = function()
	{
		alert(this.msg);
	}
}

This took me more time to figure out than I would like to admit. I am posting this in the hopes that it saves someone some time and frustration.

Posted by admin at 20 January 2009

Category: programming

Tags: , , ,

Filling out electronic forms is loads of fun… everyone can agree on that. However, when the focus is placed on the first input control, the fun level increases exponentially.

Why?

Because moving your hand from the keyboard to the mouse requires work… and nobody likes that.

In MXML and ActionScript, setting the focus to an input control is extremely easy. For example take the following component:

<?xml version="1.0" encoding="utf-8"?>
<mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml"
	layout="abolute" width="400" height="300">
	<mx:Form>
		<mx:FormItem label="Username:">
			<mx:TextInput id="uname" />
		</mx:FormItem>
		<mx:FormItem label="Password:">
			<mx:TextInput id="pwd" displayAsPassword="true" />
		</mx:FormItem>
	</mx:Form>
</mx:TitleWindow>

Typically, Title Window components are viewed as Pop Ups. When the Pop Up is launched via the PopUpManager the Title Window component gains focus within Flash player (I’ll get to why this is important later). To set the focus to a text input control, add code to the creationComplete event of the Title Window, like so:

<?xml version="1.0" encoding="utf-8"?>
<mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml"
	layout="horizontal" width="400" height="300"
	creationComplete="{onLoad(event)}">

	<mx:Script>
		<![CDATA[
		import mx.managers.FocusManager;

		private function onLoad(event:Event):void{
			focusManager.setFocus(this.uname);
		}
		]]>
	</mx:Script>

	<mx:Form>
		<mx:FormItem label="Username:">
			<mx:TextInput id="uname" />
		</mx:FormItem>
		<mx:FormItem label="Password:">
			<mx:TextInput id="pwd" displayAsPassword="true" />
		</mx:FormItem>
	</mx:Form>
</mx:TitleWindow>

Additionally, you can bypass the call to the focusManager object and call the setFocus() method of the Text Input component:

this.uname.setFocus();

Now, to the PROBLEM…

If you want to give a Text Input control focus that is part of an Application File, e.g. a Login Page, you will run into a minor problem. When you call setFocus() you will see that your component will in fact GET focus, however the cursor will not be present. Once you click in the Browser window (and not even inside of the Text Input!), the cursor will become available.

Before you can place the focus on a component within Flash Player, you need to first give focus to the Flash Player Application. This can be done via JavaScript.

The more common approach would be to add a JavaScript function to your html-wrapper and then call that function via ExternalInterface.call() Note, if you are using Flex Builder to generate your html-wrappers, add the function to the index.template.html file.

The function needed is shown below:

function setBrowserFocus(){
	document.getElementById('${application}').focus();
}

To invoke this function, use ExternalInterface.call():

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
	layout="absolute" creationComplete="onLoad(event)">

	<mx:Script>
		<![CDATA[
		import flash.external.ExternalInterface;

		private function onLoad(event:Event):void {
			ExternalInterface.call('setBrowserFocus');
			this.uname.setFocus();
		}
		]]>
	</mx:Script>

	<mx:VBox>
		<mx:HBox>
			<mx:Label text="Username:" />
			<mx:TextInput id="uname" />
		</mx:HBox>
		<mx:HBox>
			<mx:Label text="Password:" />
			<mx:TextInput id="pwd" displayAsPassword="true" />
		</mx:HBox>
	</mx:VBox>
</mx:Application>

The other approach is to place the JavaScript function directly inside of the ExternalInterface.call() method (replace \’Login\’ with the name of your .mxml application file):

ExternalInterface.call('function browserFocus(){document.getElementById(\'Login\').focus();}');

Launch the application and the cursor should be blinking inside of the Text Input.