Monday, April 06, 2009

Today I discovered the "parseNumberString()" function.

I have a textInput that is a formatted currency value. I needed to convert it to a number for calculations. I could have used a regular expression to remove the currency formatting characters. But then I found the "parseNumberString()" function.

Flex help says the parseNumberString() extracts a number from a formatted String. It examines the string from left to right and returns the first number sequence. It ignores thousands separators and includes the decimal and numbers trailing the decimal.

Here's a sample of how to use the function

import mx.formatters.NumberBase;
...
...

public function foo():void
{

var nb:NumberBase = new NumberBase();
var numValue:Number = Number( nb.parseNumberString(strCurrencyValue) );
}

Friday, January 09, 2009

The answer to my Flex 3 / Flash CS4 skinning question

Thanks to Juan Sanchez for providing me the solution when he commented on my previous blog post. He wrote...
"Try using a ClassReference for the Image source that references the skin class name in your SWC instead: http://scalenine.com/blog/2008/07/08...r-flash-skins/
source: ClassReference("Image_source");"

It worked perfectly!!!

So the CSS now looks like this:
Button { skin: Embed(skinClass="Button_skin"); }
Canvas { backgroundImage: Embed(skinClass="Canvas_backgroundImage"); }
Image { source: ClassReference("Image_source"); }
And the MXML now looks like this:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:com="com.*">
<mx:Style source="skins.css"/>
<!--- Canvas background is set using CSS --->
<Canvas>
<!--- Button skin is set using CSS --->
<mx:Button />
<!--- Now the image is set using CSS --->
<mx:Image source="{Image_source}"/>
</Canvas>
</mx:Application>

Thursday, January 08, 2009

I need help with Flex skinning using Flash CS4

I am learning how to create skins for my Flex apps in Flash CS4 and I'm finding there's multiple ways to do so.

In Flex 2 you would use ActionScript to embed a SWF that contains the skins for you app. You can do the same in Flex 3, but Adobe added the "Import Skin Artwork" feature which imports a SWC, not a SWF.

What I am trying to figure out is how to set the source of an <image> tag to the image symbol found in an "imported SWC."

To clarify my issue I'll elaborate further...

First I read...

They were all very helpful, but they showed a couple of ways to achieve the same thing, and most of the examples focused on skinning a button.

Here are the the basics that I learned:
1) Create your skin in Flash CS4.
2) Convert the skin to a symbol.
3) Publish the SWF or SWC...

  • For Flex 2:
    • Set the each symbols linkage to "Export for Actionscript."
    • Publish to a SWF that's embeded into the Flex 2 app.
  • For Flex 3:
    • Use "Convert Symbol to Flex component" (which is a available after installing the "Flex Component Kit for Flash CS3").
      Or, you could also set the each symbols linkage to "Export for Actionscript."
      I don't fully understand the difference yet.
    • Publish to a SWC and use the Flex "Import Skin Artwork" feature.

Where they differ is how to get the skin assets into flex probably due to differences between Flex 2 and 3.

In Flex 2 you would use code similar to this...


<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Script>
<![CDATA[
[Embed(source="assets/skins.swf", symbol="Canvas_backgroundImage")]
[Bindable]
public var test_background:Class;

[Embed(source="assets/skins.swf", symbol="Image_source")]
[Bindable]
public var test_image:Class;

[Embed(source="assets/skins.swf", symbol="Button_skin")]
[Bindable]
public var test_button:Class;
]]>
</mx:Script>

<mx:canvas backgroundImage="{test_background}" />
<mx:Image source="{test_image}" />
<mx:Button icon="{test_button}" />
</mx:Application>



You can use the same code in Flex 3, however Adobe introduced a new feature - "Import Skin Artwork." It's found under the File menu: File > Import > Skin Artwork...


When you "Import Skin Artwork" you have to:

1) Use a specific naming convention when creating your symbols in Flash.

2) Publish to a SWC (not a SWF).


Why publish to a SWC? The "Import Skin Artwork" functionality looks for a SWC which it will add to the library path of your Flex project. It also parses the symbol names found in the .SWC to create the CSS file used to apply the skins to your flex components.


First I created a Flash CS4 project named "skins," and I added three images and created the following symbol names:

  • Button_skin

  • Canvas_backgroundImage

  • Image_source


When I was done, I published my project creating the "skins.swc" file.


In Flex Builder 3 I imported "skins.swc" and Flex created the following "skins.css" File:


Button { skin: Embed(skinClass="Button_skin"); }
Canvas { backgroundImage: Embed(skinClass="Canvas_backgroundImage"); }
Image { source: Embed(skinClass="Image_source"); }





Note how the symbol names were parsed into the css:

  • Button_skin >> Button { skin: ...

    where "skin" is a style member of the Flex <mx:Button> component

  • Canvas_backgroundImage >> Canvas { backgroundImage: ...

    where "backgroundImage" is a style member of the Flex <mx:Canvas> component

  • Image_source >> Image { source: ...

    where "source" is a property (not a style member) of the Flex <mx:Image> component.

    This is where I believe my problem is, "source" is a property not a style member.


For more on this, read "Naming skin assets" on page 3 of the pdf "Importing Skins into Flex Builder"


Now for the MXML:


<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:com="com.*">
<mx:Style source="skins.css"/>
<!--- Canvas background is set from the CSS --->
<Canvas>
<!--- Button skin is set from the CSS --->
<mx:Button />
<!--- Image does not displayed --->
<mx:Image />
</Canvas>
</mx:Application>



I think because "source" is a property of the Flex <mx:Image> component and not a style member, it is being ignored.

However, I cannot code: [Embed(source="assets/skins.swc", symbol="Image_source")] because this throws compile error.


So, Is there a way to do this with an imported SWC?

Or do I have to create an imported SWC for skinning components and embed a SWF for image assets?


Thanks and I hope you may have learned something after reading all this as well!


Chris from flexdojo




Monday, January 05, 2009

Unable to transcode xxx.swf

Let me start by saying I’m an experienced Flex developer, but a Flash CS4 newbie.

I want to begin using Flash CS4 to create asset libraries that will be used to skin my flex apps. After creating a test swf containing some assets, I tried embedding the swf in a Flex 3 app and kept getting this error - “Unable to transcode xxx.swf.” I spent an entire day trying to resolve the problem. I searched the web for hours, but found nothing helpful.

Earlier, I installed the "Flex Skins" template into Flash CS4. I went back to that project hoping it would provide a clue. It was then I noticed the "linkage" column in the library panel. And that's how I learned the linkage on each individual symbol must be set as “Export for ActionScript” for Flex to find the symbol definitions.

Here's what messed me up...

Instead of just reporting that it can’t find the symbol definitions, Flex also reports that it can’t transcode the SWF. That led me to believe there was something wrong with the SWF. And off I went, on a wild goose chase looking for anything that would explain why flex could not embed the SWF. But in the end it was just a symbol definition problem.

I hope this helps save others hours of frustration!

Wednesday, October 15, 2008

mp3Manager.cfc for updating ID3 tags with coldfusion

I needed to modify MP3 ID3 tags on our server with Coldfusion. To do so I downloaded three different Java mp3 libraries. One did not work at all, the other two would read the ID3 tags but not update the data.

Frustrated, I went on the prowl again for another library and I found MyID3: a Java ID3 Tag Library. You will also need to download the Jakarta Regexp and Nanoxml jars as well.

Thank you Charles M. Chen for a library that's simple, well documented and works!

Also, thanks to Ray Camden for posting "Reading MP3 ID3 tags with ColdFusion" on his Coldfusion Jedi blog. That gave me a great head start.

Here's how you might use the component...

<!--- Read the ID3 comments field --->
<cfset mp3Manager = createObject("component",'components.managers.mp3Manager') />
<cfset mp3Manager.init(mp3FilePath) />
<cfset comment = mp3Manager.getComment() />

<!--- Update the ID3 comments field --->
<cfset mp3Manager = createObject("component",'components.managers.mp3Manager') />
<cfset mp3Manager.init(mp3FilePath) />
<cfset mp3Manager.setComment(strComments) />

And here is a simple version of the CFC. I hope you find it helpful.

<cfcomponent displayname="mp3Manager" output="false">  

   <!--- ============================================== --->
   <cfset variables.fileObj = "">
   <cfset variables.filename = "">
   <cfset variables.metadata = "">
   <cfset variables.metadataset = "">
   <cfset variables.id3 = "">   

   <!--- ============================================== --->
   <cffunction name="init" access="public" returnType="mp3Manager" output="false">
      <cfargument name="filename" type="string" required="false">

      <cfif structKeyExists(arguments, "filename")>
          <cfset variables.id3 = createObject("java", "org.cmc.music.myid3.MyID3") />
          <cfset variables.metadata = createObject("java", "org.cmc.music.metadata.MusicMetadata") />
          <cfset variables.metadataset = createObject("java", "org.cmc.music.metadata.MusicMetadataSet") />
          <cfset read(filename) />
      </cfif>

        <cfreturn this>
   </cffunction>

   <!--- ============================================== --->
   <cffunction name="read" access="public" returnType="void" output="false">
      <cfargument name="filename" type="string" required="true">

      <cfif not fileExists(arguments.fileName)>
         <cfthrow message="#arguments.fileName# does not exist.">
      </cfif>

      <cfset variables.filename = arguments.filename>

      <cftry>
         <cfset variables.fileObj = createObject("java","java.io.File").init(expandPath(variables.filename)) />
         <cfset variables.id3.init() />
         <cfset variables.metadataset = variables.id3.read(variables.fileObj) />
         <cfset variables.metadata = variables.metadataset.getSimplified() />
         <cfcatch>
            <cfthrow message="Invalid MP3 file: #arguments.filename# #cfcatch.message#">
         </cfcatch>
      </cftry>
   </cffunction>

   <!--- ============================================== --->
   <cffunction name="getComment" access="public" returnType="string" output="false">
      <cfreturn trim(variables.metadata.getComment())>
   </cffunction>

   <!--- ============================================== --->
   <cffunction name="setComment" access="public" returnType="void" output="false">
      <cfargument name="argComment" type="string" required="false">
      <cfset variables.metadata.setComment(argComment) />
      <cfset variables.id3.update(variables.fileObj, variables.metadataset, variables.metadata) />
   </cffunction>

   <!--- ============================================== --->
</cfcomponent>

Friday, September 26, 2008

“IE8 Compatibility Mode carries over the "darkened PNG" issue” - Please vote on my post!!!

IE8 beta 2 still has some PNG compatibility issues – specifically the "darkened PNG" issue.

Simply put, Internet Explorer darkens PNG images. If you view the same PNG image in Firefox, Opera, Safari, and Google Chrome, the colors are consistent across browsers, except for IE.

Since IE8 is supposed to resolve many CSS compatibility issues, I would hope the "darkened PNG" issue would be resolved as well.

I posted the issue on the Microsoft discussion group - microsoft.public.internetexplorer.beta.

Per Microsoft…

“Microsoft responds to the suggestions with the most votes….

If your a web developer that's sick of dealing with browser compatibility issues, please head over to the Microsoft discussion group and vote on the post with the subject “IE8 Compatibility Mode carries over the "darkened PNG" issue.”

Thanks!

Tuesday, July 01, 2008

SQL Server 2005 PIVOT Operator

For my current project I needed to convert rows of data to columns. I learned how to do this with the SQL Server 2005 PIVOT Operator.

Here's the original code...

SELECT p.user_id, pit.data_name, pi.item_value
FROM profile p
JOIN profile_item pi ON pi.profile_id = p.profile_id
JOIN profile_item_type pit ON pit.profile_item_type_id = pi.profile_item_type_id
AND pit.data_name in ('age','gender','marital_status','family_size','household_income','ethnicity')
WHERE p.user_id = 100

...and the original results...

p.user_id  pit.data_name        pi.item_value
---------  -------------        -------------
100        age                  Under 18
100        gender               Male
100        marital_status       Single
100        family_size          1
100        household_income     Under $15,000
100        ethnicity            Rather not disclose

...and now the new SQL using the PIVOT operator...

SELECT *
FROM (SELECT p.user_id, pit.data_name, pi.item_value
          FROM profile p
          JOIN profile_item pi ON pi.profile_id = p.profile_id
          JOIN profile_item_type pit ON pit.profile_item_type_id = pi.profile_item_type_id
          AND pit.data_name in ('age','gender','marital_status','family_size','household_income','ethnicity')
WHERE p.user_id = 100)m
PIVOT (MAX(item_value) FOR data_name IN ([age],[gender],[marital_status],[family_size],[household_income],[ethnicity]))p

...and the desired results...

p.user_id  age        gender    marital_status   family_size  household_income   ethnicity
---------  ---        ------    --------------   -----------  ----------------   ---------
100        Under 18   Male      Single           1            Under $15,000      Rather not disclose

You could also cross tab this without using pivot operator...

SELECT p.user_id,
MAX(CASE WHEN pit.data_name='age' THEN pi.item_value ELSE NULL END) AS age,
MAX(CASE WHEN pit.data_name='gender' THEN pi.item_value ELSE NULL END) AS gender,
MAX(CASE WHEN pit.data_name='marital_status' THEN pi.item_value ELSE NULL END) AS marital_status,
MAX(CASE WHEN pit.data_name='family_size' THEN pi.item_value ELSE NULL END) AS family_size,
MAX(CASE WHEN pit.data_name='household_income' THEN pi.item_value ELSE NULL END) AS household_income,
MAX(CASE WHEN pit.data_name='ethnicity' THEN pi.item_value ELSE NULL END) AS ethnicity
FROM profile p
JOIN profile_item pi ON pi.profile_id = p.profile_id
JOIN profile_item_type pit ON pit.profile_item_type_id = pi.profile_item_type_id
AND pit.data_name in ('age','gender','marital_status','family_size','household_income','ethnicity')
WHERE p.user_id = 100
GROUP BY p.user_id