There are quite a lot of Flex RSS feed examples out there already, but the format I’m using for my examples here would have made things easier for me to grasp earlier on, so I offer this example in case anyone else out there might likewise have an easier time with this format. This example reads in and displays the RSS feed from my WordPress-based Flex blog here. Any WordPress blog could easily be replaced in this example by changing the address of the httpRSS url and any xml-based RSS feed could be as easily parsed so long as the feed’s tags are set properly.
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="httpRSS.send()" viewSourceURL="srcview/index.html"> <mx:HTTPService id="httpRSS" url="http://www.dmallonee.com/flex/rss/"/> <mx:Panel layout="absolute" left="10" top="10" bottom="10" right="10" title="RSS Example"> <mx:VBox width="100%" horizontalAlign="left" creationCompleteEffect="Fade" paddingTop="10" paddingLeft="10" paddingRight="10" paddingBottom="10"> <mx:Repeater width="100%" id="rssItems" dataProvider="{httpRSS.lastResult.rss.channel.item}"> <mx:Label text="{rssItems.currentItem.title}" fontWeight="bold" paddingLeft="6" paddingRight="6"/> <mx:LinkButton width="100%" textAlign="left" label="{rssItems.currentItem.link}" fontWeight="normal" textDecoration="underline" click="navigateToURL(new URLRequest(event.currentTarget.label.toString()))"/> <mx:TextArea editable="false" paddingLeft="6" paddingRight="6" width="100%" height="50" borderStyle="none" htmlText="{rssItems.currentItem.description}"/> </mx:Repeater> </mx:VBox> </mx:Panel> </mx:Application>
Example: dm_simple_rss.swf
Flex Project: dm_simple_rss.zip
It wasn’t long into my Flex adventures that I’d discovered the blendMode property of UIComponents and became unspeakably delighted, as blend modes were a key feature lacking in the Juce SDK I’d previously worked with. To my dismay, it took a while before I became sufficiently accustomed with the Flex SDK that I could see the blend modes in action.
As it stands, I finally recently found a blog post on Flex blend modes by Andrew Trice, yet it’s still a bit more complicated an example than I would have felt comfortable with in my initial Flex endeavors. I think beginners might find this one a bit easier to chew on and regardless, there can never be too many examples when one is trying to learn something new.
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="640" height="400" viewSourceURL="srcview/index.html"> <mx:Image width="100%" height="100%" source="dm_blendmode.jpg" mouseFocusEnabled="false" mouseEnabled="false" mouseChildren="false"/> <mx:HSlider id="alphaSelection" minimum="0" maximum="1" x="298" y="246" liveDragging="true"/> <mx:ComboBox selectedIndex="10" id="blendModeSelection" change="gradient.blendMode=blendModeSelection.selectedLabel" x="298" y="272"> <mx:ArrayCollection> <mx:String>add</mx:String> <mx:String>alpha</mx:String> <mx:String>darken</mx:String> <mx:String>difference</mx:String> <mx:String>erase</mx:String> <mx:String>hardlight</mx:String> <mx:String>invert</mx:String> <mx:String>layer</mx:String> <mx:String>lighten</mx:String> <mx:String>multiply</mx:String> <mx:String>normal</mx:String> <mx:String>overlay</mx:String> <mx:String>screen</mx:String> <mx:String>subtract</mx:String> </mx:ArrayCollection> </mx:ComboBox> <mx:TextArea width="276" height="107" x="182" y="131"> <mx:text>There is white-black gradient layer above all of these lower graphic layers. The alpha and blendMode widgets below control the respective alpha and blendMode properties of that layer and adjusting them will illustrate the effects of the blendModes.</mx:text> </mx:TextArea> <mx:Label x="254" y="250" text="alpha"/> <mx:Label x="224" y="276" text="blendMode"/> <mx:Image width="100%" height="100%" source="dm_blendmode_gradient.jpg" alpha="{alphaSelection.value}" blendMode="multiply" mouseFocusEnabled="false" mouseEnabled="false" mouseChildren="false" id="gradient"/> </mx:Application>
Example: dm_blendmode.swf
Flex Project: dm_blendmode.zip
In working toward a simple, Flex-based CMS, I wanted to be able to load external html content without having to write numerous URLRequests in the main Flex project file, so I decided to just extend the TextArea component with a method for loading an external file.
Flex doesn’t handle html very well at all at this point, yet there are numerous ways to extend its capabilities and many others have already done just that. For sake of simplicity, I kept the functionality as it is and basically, whatever the Flex RichTextEditor component can output, this extendedTextArea can accept as input.
<?xml version="1.0" encoding="utf-8"?> <mx:TextArea xmlns:mx="http://www.adobe.com/2006/mxml"> <mx:Script> <![CDATA[ [Inspectable(defaultValue="")] private var _url:String = ""; public function set url (requestedURL:String):void { urlLoad(requestedURL); } public function get url ():String { return _url; } private function urlLoad(requestedURL:String):void { var request:URLRequest = new URLRequest(requestedURL); var loader:URLLoader = new URLLoader(); loader.load(request); loader.addEventListener(Event.COMPLETE, onComplete); } private function onComplete(event:Event):void { var loader:URLLoader = URLLoader(event.target); //replace linefeed characters since Flex displays them otherwise this.htmlText = loader.data.toString().replace(/\r|\n/gm,""); } ]]> </mx:Script> </mx:TextArea>
And here we have an example application of the above externalTextArea which loads a simple index.html file located in the same directory as the swf.
TextArea
{
cornerRadius: 5;
}
Application
{
backgroundColor: #FFFFFF;
}Example: dm_external_TextArea.swf
Flex Project: dm_external_TextArea.zip
Flex allows for the creation of various states where component properties, such as x and y position and height and width, can be be stored in one state and altered in another state and each state could then be called easily and the properties of the components in those respective states will be instantly recalled.
Here’s a little example of states and transition effects between those states. The transitions are not necessary, but they do seem to facilitate easier understanding of what is occurring when states are changed.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="640" height="480" verticalScrollPolicy="off" horizontalScrollPolicy="off" viewSourceURL="srcview/index.html"> <mx:Style source="general.css"/> <mx:states> <mx:State name="Panel 3"> <mx:SetProperty target="{panel1}" name="x" value="380"/> <mx:SetProperty target="{panel2}" name="y" value="246"/> <mx:SetProperty target="{panel3}" name="x" value="10"/> <mx:SetProperty target="{panel3}" name="y" value="10"/> <mx:SetProperty target="{panel1}" name="height" value="224"/> <mx:SetProperty target="{panel1}" name="width" value="250"/> <mx:SetProperty target="{panel3}" name="width" value="362"/> <mx:SetProperty target="{panel3}" name="height" value="460"/> </mx:State> <mx:State name="Panel 2"> <mx:SetProperty target="{panel2}" name="x" value="10"/> <mx:SetProperty target="{panel1}" name="x" value="380"/> <mx:SetProperty target="{panel1}" name="width" value="250"/> <mx:SetProperty target="{panel1}" name="height" value="224"/> <mx:SetProperty target="{panel2}" name="width" value="362"/> <mx:SetProperty target="{panel2}" name="height" value="460"/> </mx:State> </mx:states> <mx:transitions> <mx:Transition fromState="*" toState="*"> <mx:Sequence id="t1" targets="{[panel1,panel2,panel3]}"> <mx:Parallel> <mx:Move duration="400"/> <mx:Resize duration="400"/> </mx:Parallel> </mx:Sequence> </mx:Transition> </mx:transitions> <mx:Panel x="10" y="10" width="362" height="460" layout="absolute" title="Panel 1" id="panel1" click="currentState=''"> <mx:TextArea x="0" y="0" width="100%" height="100%"> <mx:text>This is an example of states and transitions in Flex 3. Click on either of the other two panels and it will be moved and resized to this panel's default position, having the effect of bringing that panel to a focal position.</mx:text> </mx:TextArea> </mx:Panel> <mx:Panel x="380" y="10" width="250" height="224" layout="absolute" title="Panel 2" id="panel2" click="currentState='Panel 2'"> <mx:TextArea x="0" y="0" width="100%" height="100%" text="States and transitions such as are exemplified here are actually quite easy with Flex and especially easier when done via Flex Builder"/> </mx:Panel> <mx:Panel x="380" y="246" width="250" height="224" layout="absolute" title="Panel 3" id="panel3" click="currentState='Panel 3'"> <mx:TextArea x="0" y="0" width="100%" height="100%"> <mx:text>Transitions can be a sequence of any number of effects used to transition between states. They aren't necessary, but they supply visual appeal and aid in understanding what is occurring when states are changed.</mx:text> </mx:TextArea> </mx:Panel> </mx:Application> |
Example: dm_states.swf
Flex Project: dm_states.zip
On my way to building my own Flex-based chat application, I came to learn that displaying smileys, or emoticons as they’re often known, is one of the most difficult things to achieve in Flash/Flex. I scoured Google once again searching for a ready-made component and found no such thing. I began a tedious endeavor to do it myself and I offer my rough stab at it here, open source and free for all.
So, the method I chose to display the smileys was to use a standard Flex Canvas which receives the smiley images as children and itself contains a child TextArea which receives the text and grows in height depending upon the size of the text. The TextArea thereby lies in back of the smileys. The Canvas’ scrollbar is set to auto and when the TextArea grows past the display height of the Canvas, the scrollbar is then displayed, allowing the text and smileys both to be scrolled simultaneously, an otherwise difficult task that actually came very easily given the method used.
There are many things I’ve overlooked and possibly bugs to be found, but in general, it works rather well. I’ve used an extended CoolRichTextEditor component which allows the controlbar to be arranged above the text area rather than below it. The component was developed by someone else and for the life of me, I can’t seem to find the developer’s site again. If someone finds it, I’d be awfully gracious if they might post a link to the site so that I might give the author proper credit. I also included a set of smileys which I assume to be under a creative commons license since the only reference I could find was on Wikimedia Commons.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 | <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" backgroundColor="#FFFFFF" width="100%" height="100%" creationComplete="init()" xmlns:ns1="*" viewSourceURL="srcview/index.html"> <mx:Script> <![CDATA[ import mx.controls.Image; import flash.events.KeyboardEvent; import mx.core.mx_internal; use namespace mx_internal; public var smiles:XML; public function init():void { //we want the textArea control to grow in height with its content textArea.height = textArea.textHeight + 10; textInput.addEventListener(KeyboardEvent.KEY_DOWN, keyDown); textInput.textArea.setFocus(); //we'll define smileys here, though these can be read in from xml file smiles = <smiles> <smile file="angry.gif" code=":{" width="20" height="20" /> <smile file="smile.gif" code=":)" width="20" height="20" /> <smile file="smile.gif" code=":-)" width="20" height="20" /> <smile file="biggrin.gif" code=":D" width="20" height="20" /> <smile file="ohmy.gif" code=":O" width="20" height="20" /> <smile file="sad.gif" code=":(" width="20" height="20" /> <smile file="sad.gif" code=":-(" width="20" height="20" /> <smile file="tongue.gif" code=":p" width="20" height="20" /> <smile file="wink.gif" code=";)" width="20" height="20" /> </smiles>; //set some initial text textInput.textArea.htmlText="Smileys example.
Available smileys: :{,:),:D,:O,:(,;),:p."; //run the smileyHandler routine right at the start smileyHandler(); } private function keyDown(event:KeyboardEvent):void { // Check to see if ENTER pressed. if (event.keyCode == Keyboard.ENTER) { smileyHandler(); } } public function smileyHandler():void { var smileyIndex:int = -1; var searchIndex:int = -1; var testSearchIndex:int = -1; var testString:String; var searchString:String = textInput.htmlText; //recurse through all smileys to see if they occur in searchString for (var x:int = 0; x < smiles.child("*").length(); x++) { //setup testString by escaping various punctuation marks before search testString = smiles.smile[x].attribute("code").toString().replace(/(\)|\()/, "\\$&"); searchIndex = searchString.search(testString); if (searchIndex >= 0) { //occurrence of this smiley found. test for previous occurence //and see if it's earlier in the text than this occurence if (testSearchIndex < 0) { //no previous smiley found, this is the first testSearchIndex = searchIndex; smileyIndex = x; } else { //previous smiley found. test if this occurrence is earlier //in text than previous occurence if (testSearchIndex > searchIndex) { testSearchIndex = searchIndex; smileyIndex = x; } } } } searchIndex = testSearchIndex; var newText:String = ""; var oldText:String = textArea.htmlText; //if no smiley found, add textInput to textArea if (searchIndex < 0) { newText = textInput.htmlText; } //recurse until no smileys found in searchString while (searchIndex >= 0) { //set replacement string as text smiley with background color so that it's semi-invisible var smileyReplaceString:String = '<FONT COLOR="#' smileyReplaceString += chatCanvas.getStyle("backgroundColor").toString(16); smileyReplaceString += '"> '; smileyReplaceString += smiles.smile[smileyIndex].attribute("code"); smileyReplaceString += ' </FONT>'; //slice searchString at index where smiley occurs and put that in textArea for operation //notice: +1 is added to searchIndex here to compensate for smiley at index 0 textArea.htmlText = oldText + newText + searchString.slice(0, searchIndex + 1); textArea.validateNow(); //get necessary coordinates and display smiley var numLines:int = textArea.mx_internal::getTextField().numLines; var smiley:Image = new Image(); smiley.source = "assets/" + smiles.smile[smileyIndex].attribute("file"); smiley.x = textArea.getLineMetrics(numLines - 1).width; smiley.y = textArea.textHeight - textArea.getLineMetrics(numLines - 1).height; chatCanvas.addChild(smiley); newText += searchString.slice(0, searchIndex) + smileyReplaceString; var codeLength:int = smiles.smile[smileyIndex].attribute("code").toString().length; searchString = searchString.slice(searchIndex + codeLength); //begin with smiley search again searchIndex = -1; testSearchIndex = -1; smileyIndex = -1; for (x = 0; x < smiles.child("*").length(); x++) { //setup testString by escaping various punctuation marks before search testString = smiles.smile[x].attribute("code").toString().replace(/(\)|\()/, "\\$&"); searchIndex = searchString.search(testString); if (searchIndex >= 0) { //occurrence of this smiley found. test for previous occurence //and see if it's earlier in the text than this occurence if (testSearchIndex < 0) { //no previous smiley found, this is the first testSearchIndex = searchIndex; smileyIndex = x; } else { //previous smiley found. test if this occurrence is earlier //in text than previous occurence if (testSearchIndex > searchIndex) { testSearchIndex = searchIndex; smileyIndex = x; } } } } searchIndex = testSearchIndex; if (searchIndex < 0) { newText += searchString; } } textArea.htmlText = oldText + newText; textArea.validateNow(); //set height of textArea to height of new text content textArea.height = textArea.textHeight + 10; //clear textInput textInput.htmlText = ""; //scroll to bottom of canvas chatCanvas.validateNow(); chatCanvas.verticalScrollPosition = chatCanvas.maxVerticalScrollPosition; } ]]> </mx:Script> <mx:VBox x="0" y="0" width="100%" height="100%"> <mx:Canvas id="chatCanvas" width="100%" height="90%" horizontalScrollPolicy="off" backgroundColor="#FFFFFF" borderStyle="solid"> <mx:TextArea width="100%" id="textArea" editable="false" fontSize="12" verticalScrollPolicy="off" borderStyle="none"> </mx:TextArea> </mx:Canvas> <ns1:CoolRichTextEditor width="100%" height="147" id="textInput" cornerRadius="5" headerHeight="0" roundedBottomCorners="true" verticalScrollPolicy="off" fontSize="12" controlBarPosition="top"/> </mx:VBox> </mx:Application> |
Example: dm_smileys.swf
Flex Project: dm_smileys.zip