The Junk In My Trunk

Flex

Flex Browser Manager, URLUtils, and modules.

by Tony on Jan.09, 2009, under Flex

My recent experience with the Flex Browser Manager and the URLUtils class and modules has been a long and anoying one… but I think I almost have it!

I know now that part of my troubles is the way my application is written - not poorly, but it makes passing url variables to modules complex as they load at different times.

Here is what happens:
The main application loads and parses the url from the browser. It then deals with any passed variables. At the same time, it gets a list of modules to load from the back end, and then loads them. Unfortunately, this process takes about 500ms to 1000ms longer - so I have all of this data, and no modules loaded to pass it to.

That in it self, is not a problem. I can just cache the data. But my data cache waits for the modules to load, then then sends the data. Well - after the modules load, then they load their own data from each other. So, by the time they are actually ready for the url variables, it’s already been sent and failed because they were not ready when it was sent.

I don’t have an easy solution for this - I could rewrite lots of code to make it work differently, but I think that this is a poor reason to rewrite the code. I can’t think of many other reasons to rewrite the code this way, so I think that it might be easier to find a hack for the url variables instead of rewritting hundreds of lines of code to work with them.

So, my solution has been to not parse the url when the main application starts. Instead, I wait for the modules to load, and then I parse the url. This way, I only have to cache the data for a few seconds at most, and all is well.

Also, since I have many modules that might or might not be loaded, each with their own information that needs to be in the url, I needed a uniform way to put these variables in the url. So I came up with the following standard:

http://www.site.com/application.html#ModuleName1=(data.data.data);ModuleName2=(data.data.data);

I use the ModuleName=(); part to seperate out each modules data. The URLUtils class has a String to Object function (strToObject I think) that can easily parse a string into an object. It uses the ; character by default, so that seemed good enough to me to use. So it would parse the url above into the following object:

{”ModuleName1″:”(data.data.data)”, “ModuleName2″:”(data.data.data)”}

So, then I wrote a simple function to parse that object into an array that I pass to each module. It parses the string “(data.data.data)” and puts each data chunk into an array element. So this array is what gets passed to each module:

["data", "data", "data"]

The functions in my main application take it no further then thata. Each data chunk can be ANY url encoded characters. (Although I haven’t written the code to url encode and decode them yet, I still have to do that.) So it is up to the modules to specify a data format that they can handle for their data chunks. Since I am the only developer, I decided to make all of my modules parse the following data chunk standard:

[adata, adata, bdata, bdata, bdata, cdata]

What that means is each data chunk starts with a single letter. This is to so that I can simply write a switch block to look for the first letter and deal with the data that way. As I said above, this isn’t needed, and each module can do whatever it wants - but this is the way I do it just to make it easier for my self.

So, here is an real example of a url that my application uses:

http://www.site.com/mainapplication.html#SearchTools=(a16.a17.o17);MediaPlayer=(s16.t3);

Here is what that url means:

The SearchTools module gets three data chunks - a16, a17, and 017. This tells it to set three search categories - two add categories and one only category. I’ll explain that is a later post.

The MediaPlayer module gets two data chunks - s16 and t3. This tells it to load song 16 and track 3.

I could also pass the MainApplication data in this same format.

So there you have it - a somewhat simple url format that an application can use to send data to it’s modules.

Leave a Comment more...

Installing Flex Builder Linux on OpenSUSE 11

by Tony on Dec.04, 2008, under Flex

For all five of us Flex developers out there running OpenSUSE 11, here is how I figured out how to install the new Flex Builder Linux alpha 4:

  • Install Eclipse (if that link doesn’t work, just search “eclipse” here)
  • Download Flex Builder Linux alpha 4 (if that link doesn’t work, just go here to find it)
  • Open a terminal window and su to root
  • Run this command (replacing the file path with the right one):
    sh flexbuilder_linux_install_a4_081408.bin
  • When prompted, specify /home/username/Adobe_flex_builder as the install location.
  • When prompted, specify /usr/share/eclipse as the eclipse folder.
  • When prompted, Install debug version of flash, not other option.
  • When done installing, exit root, and close the terminal window.
  • Open Eclipse and go to help > software updates > manage configuration.
  • Right click in the left pane and click Add > Extension Location
  • Specify the /home/username/Adobe_flex_builder directory and restart eclipse.
  • Switch your workspace (it can be the same one).
  • (optional?) Go to Window > Open Perspective and select Flex Development.

This is what I had to do to get it working. (Adobe’s install instructions were less then helpful.) I hope it helps you too! And obviously, these directions might change as new versions of Flex Builder Linux are released.

5 Comments more...

Deep Linking

by Tony on Nov.24, 2008, under Flex

I think the Adobe Flex developers invented the term “deep linking” just so they could sound a little dirty when talking about it. Unfortunately what it really is, is far less interesteing then what it sounds like.

Deep linking is what Flex 3 uses to replace the History Manager used in Flex 2. I’m sure this isn’t your first time hearing about it, as it’s not a new concept. But I needed to use it for the new Stock20 site, so I had to figure out how it works, when it does work, and how to use it.

I first started developing with it on a computer using Firefox, and it worked great. Then I switched to my other computer which uses Opera and it suddenly stopped working. This took me diving into the documentation to find out why. I knew that the documentation said it only worked with IE, Firefox, and Safari, but I figured that was a general assumption and that most modern browsers would work. I had to do some searching on ther internet, and then I found an article on Adobe labs that states that it does not work with Opera. I was surprised, but none the less, I found the answer to my problem.

So, not only did I have to setup deep linking, but I also had (have) to set up a browser detection script to warn any potential Opera users that their browser isn’t going to work with our site - at least no the way it’s supposed to. Maybe some day in the future Adobe will fix this anoying bug (or Opera will), but for now I guess we’ll only support the major three browsers.

If I was designing a site for a larger company I think I would be a little more worried, but since absolutly zero percent of Stock20’s customers use Opera, I’m not worried at all.

Anyway…. to use deep linking, you have to use Flex’s BrowserManager and IBrowserManager.
You’ll need the following:

	        import mx.events.BrowserChangeEvent;
	        import mx.managers.IBrowserManager;
	        import mx.managers.BrowserManager;
	        import mx.utils.URLUtil;
	        private var browserManager:IBrowserManager;

And then, in your applicationComplete event handler function:

				browserManager = BrowserManager.getInstance();
				browserManager.addEventListener(BrowserChangeEvent.BROWSER_URL_CHANGE, parseURL);
				browserManager.init("", "www.Stock20.com");

And here is my custom parseUrl function:

            private function parseURL(event:Event = null):void{
            	if (browserManager.fragment != "") {
	            	var urlObject:Object = URLUtil.stringToObject(browserManager.fragment);
	            	var tmpString:String;
	            	var tmpArray:Array;
	            	var i:int;
	            	var tmpModuleName:String;
	            	for (var key:String in urlObject) {
	            		tmpString = urlObject[key].toString();
	            		if (tmpString.substr(0, 1) == "(" && tmpString.substr(-1, 1) == ")") {
	            			tmpString = tmpString.slice(1, -1);
	            			tmpArray = tmpString.split(".");
	            			for (i = 0; i < tmpArray.length; i++) {
	            				if (key.toLowerCase() == "mainapplication") {
	            					handleUrlVariables(tmpArray);
	            				} else {
		            				tmpModuleName = findModuleNameFromString(key);
		            				if (tmpModuleName != "") {
		            					sendModuleData(tmpModuleName, "urlVariables", {"urlVariables":tmpArray});
		            				}
	            				}
	            			}
	            		}
	            	}
            	}
            }

Everything is fairly straight forward here (especially if you read the documentation), but I’ll explain how my custom parseUrl function works…

It first uses the URLUtil class to convert the url fragment into an object. Then it loops through that object and looks for an opening and closing () in the value of each key. If it finds one, it then splits the returned string into an array and then sends that array of values to one of the modules.

Obviously you probably wouldn’t want this type of url parsing in your application, but since my application uses modules, I had to devise a way to specify which module was to get which parts of the url. So I came up with this syntax:
modulename=(data.data.data);modulename=(data.data.data)
The modulename is obviously the name of the module. The data.data.data is any number of urlencoded text, each seperated with a period. You can seperate multiple module’s data with a semi-colon.

It may sound complex, but in reality, it’s very simple. If I need to pass data on the url to a specific module, I just write the module name, followed by it’s data, and since I can support upto 2000 characters in a url, I can store a fairly good amount of information.

What I plan to do with this is allow a user to bookmark a page, or copy a url and give it to a friend. This will allow for saved search results, and to come back to a specific song and track in our application.

Here is an example url fragment and what it would do in my application:
#searchtools=(a16.a17.o18.o20);mediaplayer=(s16.t411)
This url fragment sends data to both the SearchTools and the MediaPlayer. The SearchTools get the 4 selected categories, and the MediaPlayer gets the current song id and track id.

Leave a Comment more...

Building a Flex web application with a PHP backend

by Tony on Nov.14, 2008, under Flex

I’ve been wanting to explain how I’m building the new Stock20 site. So this post is about that.

My idea for the new stock20 site is a very fast, user friendly site that not only looks good, but is incredibly easy to use and extremely good at what it does: find music.

I built the current Stock20.com from zen-cart and customized it with flex components and php modules to work as a music store. And it does. Customers love it. The owner loves it. It works. But it has it’s problems. I wont go into most of them here, but one of it’s major problems is how hard it is to manage. It requires a full time web developer to keep it urning, and that is not a feasible solution for the future. So, in comes the new stock20 site.

It has been designed to fix most, if not all, of Stock20’s current problems. Most of them are dull and boring, but the few major ones are worth a few paragraphs.

My basic idea for the new site is a flex front end. The site should never have to “change states”, and it should be a stateless application. Taking that concept further, and using my extensive knowledge of PHP, it only made sense to use PHP for our back end operations. The site as a whole uses a MVC architecture. The model being the database back end. The view being the flex front end. The controller being the php back end.

The php back end is built using WebORB so that it can communicate to flex. It also uses the PEAR MDB2 database abstraction layer. Because php is not tied to any one server (like asp or coldfusion), and coupled with the MDB2 database abstraction layer, this allows the site to run on any server, with any operating system (that php runs on, of course). So other then a few os specific shell scripts, the whole site can run on any server and is therefore, very portable. The MDB2 database abstraction layer supports several databases, including MySQL and MSSQL, and I don’t have to rewrite any code - it just works. Very cool. The php back end is built using a module system that allows most pieces to be changed (or even totally removed) without affecting any other piece. Obviously you can’t remove the MDB2 class and expect the site to still function, but most pieces can be removed without affecting the site as a whole. The Flex front end is built the same way, using modules. When you first access index.php, a MainApplication flex file loads which contains the basic code base to run all of the other flex modules. By it self, it doesn’t provide much visually - just a preloader and then a blank screen. But it then connects to the php back end and figures out which flex modules to load for the specific “page” that was requested. It then loads these, and they appear on the screen. Each having specialized functionality: the MediaPlayer loads and handles all media requests. The SearchTools handle the display of the search tools. The SongDisplayer lists songs found with the search tools. You get my drift. The beauty of using a modualized flex front end is that components can be made to cache on the users computer so that future site visits load very quickly. Also, this caching behavior can be controlled, so that if you edit one of the modules, it loads the newest version from the server automatically.

I’ve been in the process of developing this site for over a year now. I think it would have gone quicker if I wasn’t working by my self, and if I had a full 40 hour week to work on it. But as I said above, our current zen-cart based solution requires extensive maintenance, and that eats up a large chunk of my weekly time. But the site is now starting to come together, and I fully expect to have it at least partially ready for bug testing by the end of the year, if not sooner.

The longest part was building the back end. It was almost as if I was writing my own operating system. And in a sense, I was. The MainApplication has to be able to handle several functions that you normally do not need to even think about when building a flex application. For example, if I want to move or resize one of the loaded flex modules, I have to have a function on the MainApplication to handle it, as the module can not move it self. (It actually can, but this causes a lot of extra code and pointless downloading for users.) Anything that is going to be shared between multiple modules should be loaded with the MainApplication so that the user only has to download it once, and not multiple times. So this required a significant amount of planning and organization on a scale of which I’m not used to. Especially on a one person development team!

So all in all, this project is very massive. If you just need a simple flex site, this is NOT the way to go. But if you need the ability to customize components of your site without affecting the site as a whole, want it to be very portable, want it to be multilingual, secure, fast, and very flexible… a modualized system is the way to go!

I am very excited about the new site. I really can’t wait to get people beta testing it - finding all the bugs I’ve overlooked. I plan to keep posting code snipits of things that I am working on. I think that you can expect within a few days to see some code snipit from our SearchTools module - which will probably be built with several accordions.

So stay tuned!

1 Comment more...

Custom scrolling for a flex component

by Tony on Nov.14, 2008, under Flex

Second!

Alright, it’s been like 20 hours since my first post and I don’t have any comments yet! What’s going on?!

Seriously though - here is the content:

This week I’ve been working on some custom flex components for the new Stock20 site. One is a tracks list and one is a songs list. The tracks list scrolls horizontally, and the songs list scrolls vertically.

The songs list is built using a VBox, so it’s custom scroll componets were fairly easy to build, as I had the verticalScrollPosition and maxVerticalScrollPosition properties to work with. The tracks list component was an HBox, but I needed custom scroll bars, so I had to use the scrollRect proprty and thus couldn’t use the horizontalScrollPosition properties.

Here is the main function for the custom scrolling in the songs list:

private function scrollToSelected(cNum:int):void{
            	var curObj:DisplayObject = mainVBox.getChildAt(cNum);
        		var cY:int = curObj.getBounds(mainVBox).y;
        		var nsp:int = 0;
        		if (cY + curObj.height &gt; mainVBox.height) {
        			nsp = cNum * curObj.height - (mainVBox.height - curObj.height);
        		} else if (cY &lt; 0) {
        			nsp = cNum * curObj.height;
        		} else {
        			return;
        		}
        		if (nsp &lt;= 0) {
        			mainVBox.verticalScrollPosition = 0;
        		} else if (nsp &gt;= mainVBox.maxVerticalScrollPosition) {
        			mainVBox.verticalScrollPosition = mainVBox.maxVerticalScrollPosition;
        		} else {
        			mainVBox.verticalScrollPosition = nsp;
        		}
            }

In the function above, the cNum property is the index number of the control we are trying to scroll to. The function then gets that controls DisplayObject so it can getBounds. It then uses that information along with the height information of the parent container (mainVBox) to figure out if it’s visible or not, and then change the verticalScrollPosition so that it is visible.

The scrollToSelected function in the tracks list is similar, excet I had to replace the verticalScrollPosition stuff with the scrollRect information. Here is it’s code:

            private function scrollToSelected(cNum:int):void{
            	var rect:Rectangle = tracksList.scrollRect;
            	var curObj:DisplayObject = tracksList.getChildAt(cNum);
        		var cY:int = curObj.getBounds(tracksList).x;
        		var nsp:int = 0;
        		if (cY + curObj.width &gt; rect.x + rect.width) {
        			nsp = cNum * curObj.width - (rect.width - curObj.width);
        		} else if (cY &lt; rect.x) {
        			nsp = cNum * curObj.width;
        		} else {
        			return;
        		}
        		if (nsp &lt;= 0) {
        			rect.x = 0;
        		} else if (nsp &gt;= tracksList.width) {
        			rect.x = tracksList.width - rect.width;
        		} else {
        			rect.x = nsp;
        		}
        		tracksList.scrollRect = rect;
            }
Leave a Comment more...

Looking for something?

Use the form below to search the site:

Still not finding what you're looking for? Drop a comment on a post or contact us so we can take care of it!

The best places on the internet:

My other content and some friends...

Archives

All entries, chronologically...