I was inspired by AsFusion’s Home Locator application. So, I thought I would make my own version :). Application gets data from external XML( it could be easy replaced with some backend database).
View the app here(or click on a screenshot below).

The Application:
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="init()" xmlns:controls="com.mariosh.controls.*" viewSourceURL="srcview/index.html"> <mx:Script> <![CDATA[ import mx.collections.ArrayCollection; [Bindable] private var ac:ArrayCollection; private function init():void { ac = new ArrayCollection(); for(var i:int=0; i<30; i++) { var item:Object = new Object(); item.label = "item " + i; ac.addItem(item); } } ]]> </mx:Script> <controls:BasicList x="10" y="10" width="100" height="200" dataProvider="{ac}" verticalScrollPolicy="off"/> </mx:Application>
BasicList.as
package com.mariosh.controls { import flash.events.Event; import mx.controls.List; public class BasicList extends List { private var scrollbar:ScrollBar; public function BasicList() { super(); } override protected function createChildren():void { super.createChildren(); if(!scrollbar) { scrollbar = new ScrollBar(); scrollbar.addEventListener(Event.CHANGE, thumbChange); addChild(scrollbar); } } private function thumbChange(event:Event):void { var listIndex:int = scrollbar.scrollPercentage *(this.dataProvider.length - 9); this.verticalScrollPosition = listIndex; } override protected function commitProperties():void { super.commitProperties(); scrollbar.width = 10; scrollbar.height = this.height; this.verticalScrollPosition = 10; } override protected function updateDisplayList(uW:Number, uH:Number):void { super.updateDisplayList(uW, uH); scrollbar.move(uW-scrollbar.width, 0); } } }
ScrollBar.as
package com.mariosh.controls { import flash.events.Event; import flash.events.MouseEvent; import mx.core.UIComponent; [Event(name="change", type="flash.events.Event")] public class ScrollBar extends UIComponent { private var track:Track; private var thumb:Thumb; private var _yOffset:Number; private var _yMin:Number = 0; private var _yMax:Number; public function ScrollBar() { super(); } private function thumbDown(event:MouseEvent):void { stage.addEventListener(MouseEvent.MOUSE_MOVE, thumbMove); stage.addEventListener(MouseEvent.MOUSE_UP, thumbUp); _yOffset = this.mouseY - thumb.y; } private function thumbUp(event:MouseEvent):void { stage.removeEventListener(MouseEvent.MOUSE_MOVE, thumbMove); stage.removeEventListener(MouseEvent.MOUSE_UP, thumbUp); } private function thumbMove(event:MouseEvent):void { thumb.y = this.mouseY - _yOffset; if(thumb.y <= _yMin) thumb.y = 0; if(thumb.y >= _yMax) thumb.y = _yMax; _sp = thumb.y / _yMax; dispatchEvent(new Event(Event.CHANGE)); event.updateAfterEvent(); } private var _sp:Number; public function get scrollPercentage():Number { return _sp; } //-------------------------------------------- // override methods //-------------------------------------------- override protected function createChildren():void { super.createChildren(); if(!track) { track = new Track(); track.width = 10; addChild(track); } if(!thumb) { thumb = new Thumb(); thumb.width = 10; thumb.height = 40; thumb.addEventListener(MouseEvent.MOUSE_DOWN, thumbDown); addChild(thumb); } } override protected function commitProperties():void { super.commitProperties(); track.height = this.height; _yMax = track.height - thumb.height; } } }
Track.as
package com.mariosh.controls { import mx.core.UIComponent; public class Track extends UIComponent { public function Track() { super(); } override protected function updateDisplayList(uW:Number, uH:Number):void { super.updateDisplayList(uW, uH); graphics.clear(); graphics.beginFill(0x333333); graphics.drawRect(0, 0, uW, uH); graphics.endFill(); } } }
Thumb.as
package com.mariosh.controls { import mx.core.UIComponent; public class Thumb extends UIComponent { public function Thumb() { super(); } override protected function updateDisplayList(uW:Number, uH:Number):void { super.updateDisplayList(uW, uH); graphics.clear(); graphics.beginFill(0x666666); graphics.drawRect(0, 0, uW, uH); graphics.endFill(); } } }
package com.mariosh { import flash.display.Sprite; import flash.text.TextField; import flash.text.TextFieldAutoSize; public class SizableTextField extends Sprite { public function SizableTextField() { super(); var field:TextField = new TextField(); field.wordWrap = true; field.autoSize = TextFieldAutoSize.LEFT; field.text = "Lorem ipsum dolor sit amet, " + "consectetuer adipiscing elit. Morbi tortor" + "purus, aliquet a, ornare ac, sucipit a, est." field.appendText("\n"); field.appendText("Nullam henderrit molestie erat. " + "Nunc nulla tortor, ullamcorper et," + "elementum vel, fringilla sed, dui." + "Praesent fermentum interdum orci."); addChild(field); } } }
<?xml version="1.0" encoding="utf-8"?> <!-- tooltips/BoundToolTipText.mxml --> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"> <mx:TextInput id="txtTo" width="300"/> <mx:Button label="Send" toolTip="Send e-mail to {txtTo.text}"/> </mx:Application>
<?xml version="1.0" encoding="utf-8"?> <!-- tooltips/DynamicToolTipText.mxml --> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" initialize="initApp()"> <mx:Script> <![CDATA[ import mx.managers.ToolTipManager; import mx.controls.ToolTip; import mx.events.ToolTipEvent; public function initApp():void { b1.addEventListener(ToolTipEvent.TOOL_TIP_SHOW, myToolTipChanger) } public function myToolTipChanger(event:ToolTipEvent):void { ToolTipManager.currentToolTip.text = "Click the button, " + Application.application.parameters.myName; } ]]> </mx:Script> <mx:Button id="b1" label="Click Me" toolTip="Click the button."/> </mx:Application>
<?xml version="1.0"?> <!-- asAdvanced/ASAdvancedMainModalTextEvent.mxml --> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:MyComp="myComponents.*" > <mx:Script> <![CDATA[ import flash.events.Event; private function placementChangedListener(event:Event):void { myEvent.text="placementChanged event occurred - textPlacement = " + myMT.textPlacement as String; } ]]> </mx:Script> <MyComp:ModalText id="myMT" textPlacement="left" height="40" placementChanged="placementChangedListener(event);"/> <mx:TextArea id="myEvent" width="50%"/> <mx:Label text="Change Placement" /> <mx:Button label="Set Text Placement Right" click="myMT.textPlacement='right';" /> <mx:Button label="Set Text Placement Left" click="myMT.textPlacement='left';" /> </mx:Application>
package myComponents { import mx.core.UIComponent; import mx.controls.Button; import mx.controls.TextArea; import flash.events.Event; import flash.text.TextLineMetrics; [Event(name="change", type="flash.events.Event")] [Event(name="textChanged", type="flash.events.Event")] [Event(name="placementChanged", type="flash.events.Event")] public class ModalText extends UIComponent { public function ModalText() { super(); } private var text_mc:TextArea; private var mode_mc:Button; [Embed(source="Modal2.swf", symbol="blueCircle")] public var modeUpSkinName:Class; [Embed(source="Modal2.swf", symbol="blueCircle")] public var modeOverSkinName:Class; [Embed(source="Modal2.swf", symbol="greenSquare")] public var modeDownSkinName:Class; override protected function createChildren():void { super.createChildren(); if (!text_mc) { text_mc = new TextArea(); text_mc.explicitWidth = 80; text_mc.editable = false; text_mc.text= _text; text_mc.addEventListener("change", handleChangeEvent); addChild(text_mc); } if (!mode_mc) { mode_mc = new Button(); mode_mc.label = "Toggle Editing Mode"; // If you do not have skins available, // comment out these lines. mode_mc.setStyle('overSkin', modeOverSkinName); mode_mc.setStyle('upSkin', modeUpSkinName); mode_mc.setStyle('downSkin', modeDownSkinName); mode_mc.addEventListener("click", handleClickEvent); addChild(mode_mc); } } /*** f) Implement the commitProperties() method. ***/ override protected function commitProperties():void { super.commitProperties(); if (bTextChanged) { bTextChanged = false; text_mc.text = _text; invalidateDisplayList(); } } override protected function measure():void { super.measure(); // Since the Button control uses skins, get the // measured size of the Button control. var buttonWidth:Number = mode_mc.getExplicitOrMeasuredWidth(); var buttonHeight:Number = mode_mc.getExplicitOrMeasuredHeight(); // The default and minimum width are the measuredWidth // of the TextArea control plus the measuredWidth // of the Button control. measuredWidth = measuredMinWidth = text_mc.measuredWidth + buttonWidth; // The default and minimum height are the larger of the // height of the TextArea control or the measuredHeight of the // Button control, plus a 10 pixel border around the text. measuredHeight = measuredMinHeight = Math.max(mode_mc.measuredHeight,buttonHeight) + 10; } override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void { super.updateDisplayList(unscaledWidth, unscaledHeight); // Subtract 1 pixel for the left and right border, // and use a 3 pixel margin on left and right. var usableWidth:Number = unscaledWidth - 8; // Subtract 1 pixel for the top and bottom border, // and use a 3 pixel margin on top and bottom. var usableHeight:Number = unscaledHeight - 8; // Calculate the size of the Button control based on its text. var lineMetrics:TextLineMetrics = measureText(mode_mc.label); // Add a 10 pixel border area around the text. var buttonWidth:Number = lineMetrics.width + 10; var buttonHeight:Number = lineMetrics.height + 10; mode_mc.setActualSize(buttonWidth, buttonHeight); // Calculate the size of the text // Allow for a 5 pixel gap between the Button // and the TextArea controls. var textWidth:Number = usableWidth - buttonWidth - 5; var textHeight:Number = usableHeight; text_mc.setActualSize(textWidth, textHeight); // Position the controls based on the textPlacement property. if (textPlacement == "left") { text_mc.move(4, 4); mode_mc.move(4 + textWidth + 5, 4); } else { mode_mc.move(4, 4); text_mc.move(4 + buttonWidth + 5, 4); } // Draw a simple border around the child components. graphics.lineStyle(1, 0x000000, 1.0); graphics.drawRect(0, 0, unscaledWidth, unscaledHeight); } /*** i) Add methods, properties, and metadata. ***/ // The general pattern for properties is to specify a private // holder variable. private var _textPlacement:String = "left"; // Create a getter/setter pair for the textPlacement property. public function set textPlacement(p:String):void { _textPlacement = p; invalidateDisplayList(); dispatchEvent(new Event("placementChanged")); } // The textPlacement property supports data binding. [Bindable(event="placementChanged")] public function get textPlacement():String { return _textPlacement; } private var _text:String = "ModalText"; private var bTextChanged:Boolean = false; // Create a getter/setter pair for the text property. public function set text(t:String):void { _text = t; bTextChanged = true; invalidateProperties(); dispatchEvent(new Event("textChanged")); } [Bindable(event="textChanged")] public function get text():String { return text_mc.text; } // Handle events that are dispatched by the children. private function handleChangeEvent(eventObj:Event):void { dispatchEvent(new Event("change")); } // Handle events that are dispatched by the children. private function handleClickEvent(eventObj:Event):void { text_mc.editable = !text_mc.editable; } } }


I’m Mariusz Tkaczyk.