Archive for November, 2008
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.
Punched Out!
by Tony on Nov.17, 2008, under Uncategorized
Well, today I had a punch biopsy. I thought that the actual procedure was going to the scary part, but it turns out that my pregnant wife passing out and landing on the floor right as they cut me was the really scary part!
I thought the procedure was going to hurt, but they numbed it completly and I didn’t feel a thing. It was almost fun actually. But Tara passed our right as they started cutting me, so I was on the table bleeding and my poor wife was on the floor and there wasn’t much I could do to help her. I tried to catch her as she fell, but I wasn’t in a position where I could. But she woke up right away, and the doctor wasn’t worried. We also called her mid-wife and she wasn’t concerned either. So I guess we are in the clear - but it was an experience we will probably remember for a long time!
New Wallpaper - openSUSE 11 with 3d desktop effects
by Tony on Nov.17, 2008, under Uncategorized
I am the kind of person who is minimalistic. For the majority of the past 11 years, I’ve had nothing but a black desktop, with no wall paper, no desktop effects, and everything functional. I had two reasons for this: 1) It was fast and didn’t slow my computer down. 2) It was easy on the eyes - easy to find a white mouse on a black desktop. (I’m visually impaired.)
But since I’ve installed OpenSUSE 11 on my computer and enabled 3d Desktop Effects, my computer has actually been MORE functional, not less. And it still runs even processor intensive applications very easily without slowing down. So I thought it was high time for me to break the black and take the plunge into a graphical desktop wallpaper. But I’ve never liked anything I’ve ever found on the internet, and finding a premade wallpaper that fits my dual monitor setup without stretching is slim pickings.
So, I made my own. This is a simple black background with a dark gray gradient and the OpenSUSE logo with a drop shadown. It doesn’t look like much in the picture becuase you are probably viewing it on a single monitor, but if viewed on a dual monitor setup like I have, it looks great because the logo is on the bottom left corner of the right monitor.
Also, I have 3d desktop effects enabled. You can’t see them here, but I have 3d cube with 6 virtual desktops, a zoomed out mirrored image of all 6 virtual desktops if you move your mouse to the top left corner of the screen, and a card deck view of all open windows accecable with a keyboard shortcut.
What you can see here is my terminal window that is “embedded” in my desktop on my right monitor. Again, it looks silly in this screenshot, but on a dual monitor setup, it looks great and makes a lot of sense. Also, it appears on all 6 of my virtual desktops. I put embedded in quotes because technically it’s not embedded, it just appears to be. I’m using compiz to make the window appear that way.
Over all this setup is extreamly functional, and also visually pleasing. Thus my reason for sharing it.
I also have to use Harvest for work, so I’m in the process of setting up a script to use conky and some icons to keep my harvest timesheet right on my desktop. I’ll update that if I get it working. (Right now, harvet’s api isn’t working right.)
Oh, and I’ve also written a custom cron script to check my gmail account every 5 minutes and display a little popup notification on my screen if I get new email. I think gmail has a notifier for linux now, but I wanted to write my own so I could customize how it works. It stays on the screen until I click it so that I notice it. (I have limited periferal vision, so I don’t always notice it right away.)
UPDATE:
I just found out that harvest doesn’t allow api access with their free accounts (I have a free account because that is all I need). So, the harvest thing wont be happening I guess. Too bad. ![]()
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!
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 > mainVBox.height) { nsp = cNum * curObj.height - (mainVBox.height - curObj.height); } else if (cY < 0) { nsp = cNum * curObj.height; } else { return; } if (nsp <= 0) { mainVBox.verticalScrollPosition = 0; } else if (nsp >= 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 > rect.x + rect.width) { nsp = cNum * curObj.width - (rect.width - curObj.width); } else if (cY < rect.x) { nsp = cNum * curObj.width; } else { return; } if (nsp <= 0) { rect.x = 0; } else if (nsp >= tracksList.width) { rect.x = tracksList.width - rect.width; } else { rect.x = nsp; } tracksList.scrollRect = rect; }
content v0.1
by Tony on Nov.13, 2008, under Uncategorized
Here is the infamous “first post”.
“Hopefully not the last.”
I’ll get more content and links up asap (meaning, don’t hold your breath).
