Why Alivepdf generate double table header? - actionscript-3

I'm attempting to create a pdf table on my flex application using AlivePdf:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:mh="mh.components.*"
layout="absolute" width="500" height="500">
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import org.alivepdf.colors.RGBColor;
import org.alivepdf.display.Display;
import org.alivepdf.drawing.Caps;
import org.alivepdf.fonts.FontFamily;
import org.alivepdf.fonts.Style;
import org.alivepdf.grid.Grid;
import org.alivepdf.images.ImageFormat;
import org.alivepdf.layout.Orientation;
import org.alivepdf.layout.Resize;
import org.alivepdf.layout.Size;
import org.alivepdf.layout.Unit;
import org.alivepdf.pages.Page;
import org.alivepdf.pdf.PDF;
import org.alivepdf.saving.Method;
import org.alivepdf.visibility.Visibility;
import org.alivepdf.grid.*;
private var myPDF:PDF;
//print chart in pdf format
protected function savePDF(e:MouseEvent):void
{
var myPDF:PDF = new PDF ( Orientation.PORTRAIT, Unit.MM);
myPDF.setDisplayMode(Display.FULL_PAGE);
myPDF.addPage();
myPDF.setXY( 10, 70);
myPDF.textStyle ( new RGBColor ( 0x000000 ) );
var dp:ArrayCollection = new ArrayCollection();
dp.addItem( { firstName : "Bob Geldorf akjaskaj skajs as kajs kaj k dklfj sdkfjl sdkjf ksdj fkjs dkfj ksdj ", lastName : "Groove", city : "Paris" } );
dp.addItem( { firstName : "Bob", lastName : "Wise", city : "Paris" } );
dp.addItem( { firstName : "Bob", lastName : "Wise", city : "Paris" } );
dp.addItem( { firstName : "Bob", lastName : "Wise", city : "Paris" } );
var grid:Grid = new Grid ( dp.toArray(), 200, 100, new RGBColor (0x00DEFF));
myPDF.addGrid( grid, 0, 0, true );
myPDF.save( Method.REMOTE, "coldfusion/pdf.cfm", "inline", "test.pdf" );;
}
]]>
</mx:Script>
<mx:VBox width="100%" height="100%">
<mx:HBox width="100%" backgroundColor="#FFFFFF">
<mx:Spacer width="100%"/>
<mx:Button horizontalCenter="0" label="Save to PDF" height="22" click="savePDF(event)" id="savePDFBtn" toolTip="SAVE TO PDF"/>
</mx:HBox>
</mx:VBox>
The strange thing is that the script create a table with double header and I don't know why. You can see the pdf generated at this link: https://docs.google.com/viewer?url=prestitiinpdap.biz/pdf/myPDF.pdf

Which version of the library do you use? I have tried to compile your code with the current version 0.1.5RC and the compiler could not find some classes.
After correction of the class paths I have found that the "new Grid(...)" constructor needs 7 parameters (in your case only 4).
Another issue is "width" in "Grid(...)". I don't know, what the developers wanted to express with it. I could get I normal view only with 60.
I have got the following PDF after all:
Here is my code:
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" width="500" height="500">
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import org.alivepdf.colors.RGBColor;
import org.alivepdf.data.Grid;
import org.alivepdf.display.Display;
import org.alivepdf.drawing.Caps;
import org.alivepdf.fonts.FontFamily;
import org.alivepdf.fonts.Style;
import org.alivepdf.images.ImageFormat;
import org.alivepdf.layout.Orientation;
import org.alivepdf.layout.Resize;
import org.alivepdf.layout.Size;
import org.alivepdf.layout.Unit;
import org.alivepdf.pages.Page;
import org.alivepdf.pdf.PDF;
import org.alivepdf.saving.Method;
import org.alivepdf.visibility.Visibility;
import org.alivepdf.layout.*;
private var myPDF:PDF;
protected function savePDF(e:MouseEvent):void
{
var myPDF:PDF = new PDF( Orientation.PORTRAIT, Unit.MM);
myPDF.setDisplayMode( Display.FULL_PAGE, Layout.SINGLE_PAGE );
var newPage:Page = new Page ( Orientation.PORTRAIT, Unit.MM);
myPDF.addPage(newPage);
myPDF.textStyle ( new RGBColor ( 0x000000 ) );
var dp:ArrayCollection = new ArrayCollection();
dp.addItem( { firstName : "Bob Geldorf akjaskaj skajs as kajs kaj k dklfj sdkfjl sdkjf ksdj fkjs dkfj ksdj ", lastName : "Groove", city : "Paris" } );
dp.addItem( { firstName : "Bob", lastName : "Wise", city : "Paris" } );
dp.addItem( { firstName : "Bob", lastName : "Wise", city : "Paris" } );
dp.addItem( { firstName : "Bob", lastName : "Wise", city : "Paris" } );
//var grid:Grid = new Grid ( dp.toArray(), 200, 100, new RGBColor (0x00DEFF));
var grid:Grid = new Grid (dp.toArray(), 60, 100, new RGBColor(0x00DEFF), new RGBColor (0xFFFFFF), false, new RGBColor (0x000000));
myPDF.addGrid( grid, 0, 0, true );
//myPDF.save( Method.REMOTE, "coldfusion/pdf.cfm", "inline", "test.pdf" );
var f:FileReference = new FileReference();
var b:ByteArray = myPDF.save(Method.LOCAL);
f.save(b, "test.pdf");
}
]]>
</fx:Script>
<mx:VBox width="100%" height="100%">
<mx:HBox width="100%" backgroundColor="#FFFFFF">
<mx:Spacer width="100%"/>
<mx:Button horizontalCenter="0" label="Save to PDF" height="22" click="savePDF(event)" id="savePDFBtn" toolTip="SAVE TO PDF"/>
</mx:HBox>
</mx:VBox>
</s:Application>
Try it, may be it will help you.

When creating a PDF with a Grid, I had the same problem of duplicate headers, as reported here. It's a few years after your problem, but since i came across it now, here's my solution...
To ensure using the latest AlivePDF version, I have downloaded the latest source code from their SVN: http://alivepdf.googlecode.com/svn/trunk/AlivePDFBeta/src
I believe this is distributed as AlivePDF 0.1.5 RC, however the distributed SWCs seem to have differences in some method signatures.
While scanning the AlivePDF source code for behaviour related with adding the Grid header, I noticed the class org.alivepdf.pdf.PDF, public method addGrid.
That method is indeed adding the Grid header 2 times, possibly by mistake.
This was fixed by commenting lines 4178 to 4180, as shown in the following source code.
Full method with the commented portion included:
public function addGrid ( grid:Grid, x:Number=0, y:Number=0, repeatHeader:Boolean=true ):void
{
if ( textColor == null )
throw new Error("Please call the setFont and textStyle method before adding a Grid.");
currentGrid = grid;
currentGrid.x = x;
currentGrid.y = y;
var i:int = 0;
var j:int = 0;
currentGrid.generateColumns(false);
columns = currentGrid.columns;
var row:Array;
columnNames = new Array();
var lngColumns:int = columns.length;
var item:*;
for (i = 0; i< lngColumns; i++)
columnNames.push ( new GridCell(columns[i].headerText, currentGrid.headerColor ) );
var rect:Rectangle = getRect ( columnNames, currentGrid.headerHeight );
if ( checkPageBreak(rect.height) )
addPage();
// Commented to avoid the duplicate header issue:
//setXY (x +currentGrid.x, y+getY() );
//addRow( columnNames,'', rect);
//endFill();
setXY ( x+getX(), y+getY() );
addRow( columnNames, GridRowType.HEADER, rect );
if (grid.cells == null)
grid.generateCells();
var buffer:Array = grid.cells;
var lngRows:int = buffer.length;
for (i = 0; i< lngRows; i++)
{
item = buffer[i];
row = new Array();
for (j = 0; j< lngColumns; j++)
{
row.push (item[columns[j].dataField] != null ? item[columns[j].dataField] : "");
nb = Math.min(nb,nbLines(columns[j].width,row[j]));
}
row = buffer[i];
rect = getRect ( row, currentGrid.rowHeight );
setX ( x + getX());
if ( checkPageBreak(rect.height) )
{
addPage();
setXY ( x+getX(),nextPageY );
//setXY ( x+getX(),y+getY() ); hacked to allow user to set the next Page Y of Grid
if ( repeatHeader )
{
addRow (columnNames, GridRowType.HEADER, getRect(columnNames, currentGrid.headerHeight) ); // header
setX ( x + getX() );
}
}
if ( grid.useAlternativeRowColor && Boolean(isEven = i&1) )
addRow( row, GridRowType.ALTERNATIVE, rect );
else addRow( row, GridRowType.NORMAL, rect );
}
}

Related

Search inside a DataGrid

I have been fighting with some code I wrote in the past and trying to tweak it. Currently my search only searches for a matching first character of a word. I need to search more in depth. For instance if I search for planet in this string:
"Earth is a planet"
I get nothing, but if I search for planet in this next string:
"Planet earth is amazing"
I get the data grid to show just that line.
I want to be able to search for a word the shows the line regardless of whether its in the beginning of a string or end of one.
Can someone help me out? Thanks in advance.
import fl.controls.DataGrid;
import fl.controls.TextInput;
import fl.controls.dataGridClasses.DataGridColumn;
import fl.data.DataProvider;
var voddb:DataProvider = new DataProvider();
voddb.addItem({title:"Earth is a planet", detail:"ALE 0110"});
voddb.addItem({title:"Planet Earth", detail:"ALE 0210"});
voddb.addItem({title:"Jupiter is a planet", detail:"ALE 0310"});
voddb.addItem({title:"Aplanet Jupiter", detail:"ALE 0410"});
voddb.addItem({title:"Another amazing planet is mars", detail:"ALE 0510"});
voddb.addItem({title:"Planets include earth and mars:", detail: "ALE 0610"});
vodTextInput.addEventListener(Event.CHANGE, changeHandler);
var titleCol:DataGridColumn = new DataGridColumn("title");
titleCol.headerText = "Title";
var detailCol:DataGridColumn = new DataGridColumn("detail");
detailCol.headerText = "Details";
detailCol.sortOptions = Array.DESCENDING;
vodDataGrid.addColumn(titleCol);
vodDataGrid.addColumn(detailCol);
vodDataGrid.dataProvider = voddb;
function changeHandler(event : Event) : void
{
var arr : Array = voddb.toArray();
var filteredArr : Array = arr.filter(filterDataProvider);
vodDataGrid.dataProvider = new DataProvider(filteredArr);
}
function filterDataProvider(obj : Object, idx : String, arr : Array) : Boolean
{
var txt1 : String = vodTextInput.text;
var txt2 : String = obj.title.substr(0, txt1.length);
if (txt1.toLowerCase() == txt2.toLowerCase())
{
return true;
}
return false;
}
You can use indexOf to search for the string.
function filterDataProvider(obj : Object, idx : int, arr : Array) : Boolean
{
var txt1 : String = vodTextInput.text.toLowerCase();
var txt2 : String = obj.title.toLowerCase();
return txt2.indexOf(txt1) >= 0;
}

Listing huge amount files and directories include subdirectories in Adobe AIR

I am trying to list files and directories and copy all files existing into any other folder.
By the way, there are many files and directories more than 1000 000+.
Here is a part of code.
private function getFileList(sourceDir:String):void{
var file:File = File.userDirectory.resolvePath(sourceDir);
file.addEventListener(FileListEvent.DIRECTORY_LISTING, directory_listing);
file.getDirectoryListingAsync();
}
private function directory_listing(e:FileListEvent):void{
var getfiles:Array = e.files;
for each(var item:File in e.files){
if(checkDir(item.nativePath)){
// It is a directory, more logic!
totalDirNum++;
item.addEventListener(FileListEvent.DIRECTORY_LISTING, directory_listing);
item.getDirectoryListingAsync();
}
else{
// It is a file, more logic!
totalFileNum++;
if(analyzeFile(item) === true){
if(overwriteChk.selected === false){ // Don't overwrite same file
if(checkFile(destinationDir.nativePath + "\\" + item.name) === false){
copyInto(item, destinationDir.resolvePath(destinationDir.nativePath + "\\" + item.name));
copiedNum++;
}
else uncopiedNum++;
}
else{ // Overwrite same file
copyInto(item,destinationDir.resolvePath(destinationDir.nativePath + "\\" + item.name));
copiedNum++;
}
}
else{
skippedNum++;
}
}
}
As you see, it executes recursive directory_listing().
In case of little files and directories, it works clearly.
But, for example, in the following case it not works clearly(appear not responding.)
Root Directory : A!
A includes 500 000+ subdirectories.
Each subdirectories include 4 or 5 files and one or two subdirectories.
And also the subdirectoy include a 4 or 5 files.
So, I need to copy all files of "A" folder to the specific folder (B!).
Program is stopped in first before loop. i.e. Named "A" folder include huge subfolders, so when program run to select a "A" folder, then it is stopped just in "A" folder listing(stopped at getDirectoryListingAsyc()). So, actually it is not called recursive.
Here is my full source code.
<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
width="800" height="600"
title="eveningCopier - Niao Jina"
creationComplete="initApp()">
<fx:Script>
<![CDATA[
import mx.controls.Alert;
public var sourceDir:File;
public var destinationDir:File;
public var totalDirNum:uint;
public var totalFileNum:uint;
public var copiedNum:uint;
public var skippedNum:uint;
public var uncopiedNum:uint;
public var startTime:String;
public var finishTime:String;
/**
* Boot Function
**/
public function initApp():void{
sourceBtn.addEventListener(MouseEvent.CLICK, click_sourceBtn);
destinationBtn.addEventListener(MouseEvent.CLICK, click_destinationBtn);
startBtn.addEventListener(MouseEvent.CLICK, click_startBtn);
totalDirNum = 0;
totalFileNum = 0;
copiedNum = 0;
skippedNum = 0;
uncopiedNum = 0;
}
/**
* Event Listener when click "Source" button
**/
protected function click_sourceBtn(e:MouseEvent):void{
sourceDir = new File();
sourceDir.addEventListener(Event.SELECT, select_source);
sourceDir.browseForDirectory("Please select a source directory...");
}
private function select_source(evt:Event):void {
sourceTxt.text = sourceDir.nativePath;
}
/**
* Event Listener when click "Destination" button
**/
protected function click_destinationBtn(e:MouseEvent):void{
destinationDir = new File();
destinationDir.addEventListener(Event.SELECT, destination_select);
destinationDir.browseForDirectory("Please select a source directory...");
}
private function destination_select(evt:Event):void {
destinationTxt.text = destinationDir.nativePath;
}
/**
* Event Listener when click "Start" button
**/
protected function click_startBtn(e:MouseEvent):void{
if(sourceTxt.text == "") Alert.show("Please select a source directory", "Warning");
else if(destinationTxt.text == "") Alert.show("Please select a destination directory", "Warning");
if(checkDir(sourceTxt.text) === false) Alert.show("A selected Source folder:\n" + sourceTxt.text + "\n is not exist. Please check!", "Warning");
else if(checkDir(destinationTxt.text) === false) Alert.show("A selected Destination folder:\n" + destinationTxt.text + "\n is not exist. Please check!", "Warning");
//Alert.show(checkFile("D:\\New Folder\\f.txt").toString());
//Alert.show(checkDir("D:\\New Folder\\f.txt").toString());
workedTextArea.text = "";
currentLabel.text = "";
timeLabel.text = "";
totalDirLabel.text = "";
totalFileLabel.text = "";
copiedLabel.text = "";
skippedLabel.text = "";
uncopiedLabel.text = "";
totalDirNum = 0;
totalFileNum = 0;
copiedNum = 0;
skippedNum = 0;
uncopiedNum = 0;
startTime = getNow() + "\n";
getFileList(sourceTxt.text);
}
/**
* Get a current date and time as format - YYYY-MM-DD HH:II:SS
*
* #return String
**/
public function getNow():String{
var now:Date = new Date();
return now.getFullYear() + "-" + now.getMonth() + "-" + now.getDate() + " " + now.getHours() + ":" + now.getMinutes() + ":" + now.getSeconds();
}
/**
* Check if the directory is exist.
* #param dirName:String Path of the directory
* #return Boolean true or false
**/
private function checkDir(dirName:String):Boolean{
var dir:File = File.userDirectory.resolvePath(dirName);
return dir.isDirectory;
}
/**
* Check if the file is exist.
* #param fileName:String Path of the file
* #return Boolean true or false
**/
private function checkFile(fileName:String):Boolean{
var file:File = File.userDirectory.resolvePath(fileName);
return file.exists;
}
/**
* Ananlyze a structure of files and directory
* If is a folder, loop in its subfolder.
* If is a file, copy to the destination folder
*
* #param sourceDir:String
**/
private function getFileList(sourceDir:String):void{
var file:File = File.userDirectory.resolvePath(sourceDir);
file.addEventListener(FileListEvent.DIRECTORY_LISTING, directory_listing);
file.getDirectoryListingAsync();
}
private function directory_listing(e:FileListEvent):void{
var getfiles:Array = e.files;
for each(var item:File in e.files){
trace(item.nativePath);
currentLabel.text = "Latest In : " + item.nativePath;
if(checkDir(item.nativePath)){
// It is a directory, more logic!
totalDirNum++;
item.addEventListener(FileListEvent.DIRECTORY_LISTING, directory_listing);
item.getDirectoryListingAsync();
}
else{
// It is a file, more logic!
totalFileNum++;
if(analyzeFile(item) === true){
if(overwriteChk.selected === false){ // Don't overwrite same file
if(checkFile(destinationDir.nativePath + "\\" + item.name) === false){
copyInto(item, destinationDir.resolvePath(destinationDir.nativePath + "\\" + item.name));
copiedNum++;
}
else uncopiedNum++;
}
else{ // Overwrite same file
copyInto(item, destinationDir.resolvePath(destinationDir.nativePath + "\\" + item.name));
copiedNum++;
}
}
else{
skippedNum++;
}
}
}
finishTime = getNow();
timeLabel.text = startTime + finishTime;
totalDirLabel.text = "Total Dir : " + totalDirNum;
totalFileLabel.text = "Total Files : " + totalFileNum;
copiedLabel.text = "Copied Files : " + copiedNum;
skippedLabel.text = "Skipped Files : " + skippedNum;
uncopiedLabel.text = "Uncopied Files : " + uncopiedNum;
}
/**
* Copy files
* #param sourceFilePointer:File
* #param destinationDirPointer:File
* #return void
**/
private function copyInto(sourceFilePointer:File, destinationDirPointer:File):void{
sourceFilePointer.copyTo(destinationDirPointer, true);
if(logsChk.selected === true)
workedTextArea.text += sourceFilePointer.nativePath + "\n";
}
private function analyzeFile(filePointer:File):Boolean{
//Alert.show(filePointer.extension + "\n" + filePointer.size + "\n" + filePointer.name.indexOf("#"));
if((filePointer.extension) == null && (filePointer.size/1024 > 2) && (filePointer.name.indexOf("#") == -1))
return true;
else
return false;
}
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:BorderContainer width="100%" height="100%">
<s:VGroup width="90%" height="5%" left="0">
<s:HGroup width="100%">
<s:Button id="sourceBtn" label="Source"/>
<s:TextInput id="sourceTxt" width="90%" fontSize="11"/>
</s:HGroup>
<s:HGroup width="100%">
<s:Button id="destinationBtn" label="Destination"/>
<s:TextInput id="destinationTxt" width="90%" fontSize="11"/>
</s:HGroup>
</s:VGroup>
<s:Button id="startBtn" label="Start" height="48" top="0" right="0"/>
<s:HGroup top="50" width="100%">
<s:Label id="currentLabel" width="90%" height="19" text="Latest In : "
textAlign="left" verticalAlign="middle"/>
<s:CheckBox id="overwriteChk" label="Overwrite" selected="false"/>
<s:CheckBox id="logsChk" label="Logs" selected="false"/>
</s:HGroup>
<s:TextArea id="workedTextArea" x="0" top="77" width="100%" height="90%" editable="false"/>
<s:HGroup width="100%" height="5%" bottom="0">
<s:Label id="timeLabel" width="20%" height="100%" textAlign="center" verticalAlign="middle" fontSize="11"/>
<s:Label id="totalDirLabel" width="16%" height="100%" textAlign="center" verticalAlign="middle"/>
<s:Label id="totalFileLabel" width="16%" height="100%" textAlign="center" verticalAlign="middle"/>
<s:Label id="copiedLabel" width="16%" height="100%" textAlign="center" verticalAlign="middle"/>
<s:Label id="skippedLabel" width="16%" height="100%" textAlign="center" verticalAlign="middle"/>
<s:Label id="uncopiedLabel" width="16%" height="100%" textAlign="center" verticalAlign="middle"/>
</s:HGroup>
</s:BorderContainer>
</s:WindowedApplication>
Your problem lies within the execution time. If you're trying to perform everything in one go it will use all the CPU it can get. If one thread is being executed for longer than X seconds (usually 15), flash will abort it saying it takes too much.
Before starting your loop, take a timestamp with getTimer() and in the loop, in the beginning of your loop check if the startTimestamp - currentTimestamp is less than 5000 (5 seconds). If it is, break the array and start it over (with or without delay, flash will allow it) from the place you've left.
For this type of operations it would make sense to use workers, check this.
Here's an abstract example:
var counter:int = 0; // our progress
var startTime:int;
function increaseCounter():void
{
startTime = getTimer();
while(true) // infinite loop
{
if (getTimer() - startTime > 5000)
{
increaseCounter();
break;
}
counter++;
if (counter >= int.MAX_VALUE) // our custom loop exit
{
trace(counter);
break;
}
}
}
Though this thread seems to be quite old but I am posting a working code here which I wrote for searching files with given search string. It goes through all subfolders and pretty fast to respond in comparison to File.getDirectoryListing()
Here is my code
protected function performSearch(event:MouseEvent):void
{
searchResults = new Array(); // instance variable
foldersToBeSearched = new Array(); // instance variable
// keep file search list empty at start
fileSearchList.dataProvider = searchResults;
// instance level variable to store search string
searchString = searchText.text.toLowerCase();
// add root folder to array
foldersToBeSearched.push(File.applicationStorageDirectory);
findoutFolderNames(File.applicationStorageDirectory);
// keep and eye on folder search counter
setTimeout(checkAsyncFolderCounter, 500);
// show controls if search is on
showHideControlsAsPerSearchNeed();
}
// Because folder search is async hence use timeout to confirm if all folders are listed
private function checkAsyncFolderCounter():void
{
if(foldersToBeSearched.length === counterCapturedLast)
{
// I am done searching all folders and subfolder
// show this data now
fileSearchList.dataProvider = searchResults;
trace(searchResults.length);
}
else
{
// I am not yet done with folders...keep finding
counterCapturedLast = foldersToBeSearched.length;
setTimeout(checkAsyncFolderCounter, 500);
}
}
// Find out all folders in this folder
private function findoutFolderNames(folder:File):void
{
folder.addEventListener(FileListEvent.DIRECTORY_LISTING, directoryListingHandler);
folder.getDirectoryListingAsync();
}
// CHECK ALL FILES AND FOLDER AND FIND FOR SEARCH STRING OTHERWISE ADD FOLDER TO SEARCH FOLDERS LIST
private function directoryListingHandler(event:FileListEvent):void
{
event.target.removeEventListener(FileListEvent.DIRECTORY_LISTING, directoryListingHandler);
var list:Array = event.files;
for (var i:uint = 0; i < list.length; i++)
{
var file:File = list[i];
if(file.isDirectory)
{
foldersToBeSearched.push(file);
findoutFolderNames(file);
}
else
{
if(file.extension === "drl" && file.name.toLowerCase().indexOf(searchString) !== -1)
{
searchResults.push({label: file.name, creationDate: file.creationDate, nativePath: file.nativePath});
}
}
}
trace("Folder Count " + foldersToBeSearched.length);
}

ArcGIS API for Flex : dynamic InfoSymbols

I am trying to add some InfoSymbols in my map, here is what I did :
<esri:InfoSymbol id="infoSymbol1">
<esri:infoRenderer>
<fx:Component>
<s:DataRenderer>
<s:layout>
<s:VerticalLayout/>
</s:layout>
<s:Image id="eventImg" source="{imgSource}"/>
<s:Label id="eventName" text="{eventTitle}"/>
</s:DataRenderer>
</fx:Component>
</esri:infoRenderer>
</esri:InfoSymbol>
And I am filling a list from the data passed to the view, ( the application is a mobile view based app)
public function fillDataGrid():void {
for each(var object:Object in data) {
initDG.addItem(object);
drawEvent(object);
}
}
Finally I add the InfoSymbols the drawEvent(objt) method :
private function drawEvent(object:Object):void{
var myGraphicText:Graphic = new Graphic(new WebMercatorMapPoint(
object.local.longitude, object.local.latitude));
var event:InfoSymbol = new InfoSymbol();
imgSource = "http://192.168.0.22:3000" + object.logo_thumb_url;
eventTitle = object.name;
event = infoSymbol1;
myGraphicText.symbol = event;
myGraphicsLayer.add(myGraphicText);
}
of course imgSource and eventTitle are Bindable,
The issue is that I am getting
Description Resource Path Location Type
1120: Access of undefined property eventTitle.
And the same message for imgSource,
Any help would be much appreciated !!
You need to declare eventTitle before you assign a value to it.
var eventTitle:String = object.name;

HttpService Error #2096

I've written a Httpservice to get data from server but when I tried to run the service it got me the error (#2096). Below is my code:
package
{
import flash.net.URLRequestHeader;
import mx.collections.ArrayCollection;
import mx.controls.Alert;
import mx.messaging.AbstractConsumer;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
import mx.rpc.http.HTTPService;
public class JSONDataLoader
{
private var httpService:HTTPService;
private var errVO:ErrVO;
[Bindable]
public var errAC:ArrayCollection = new ArrayCollection();
[Bindable]
public var errStr:String;
public function JSONDataLoader(url:String)
{
httpService = new HTTPService();
httpService.url = url;
httpService.method = "POST";
httpService.contentType = "application/json";
var headerParams:Object = new Object();
headerParams["Host"] = "192.168.11.59:3333";
headerParams["Content-Length"] = 347;
httpService.headers = headerParams;
var parameters:Object = new Object();
parameters["FromDate"] = "01-01-2013 18:30";
parameters["Location"] = "String content";
parameters["LocationId"] = 2147483647;
parameters["ReportId"] = 9223372036854775807;
parameters["ReportName"] = "String content";
parameters["Team"] = "17,22,30,1,40,53,55,69,70,73,77";
parameters["TeamId"] = 2147483647;
parameters["ToDate"] = "01-01-2013 18:30";
httpService.send(parameters);
httpService.addEventListener(ResultEvent.RESULT, resultHandler);
httpService.addEventListener(FaultEvent.FAULT, faultHandler);
}
private function resultHandler(event:ResultEvent):void
{
var rawData:String = String(event.result);
var obj:Object = JSON.parse(rawData);
Alert.show("Data: " + rawData);
}
private function faultHandler(event:FaultEvent):void
{
errStr = event.fault.faultString+" "+event.message;
Alert.show("Error!!!" + errStr);
}
}
}
What i am doing worng here. Is there problem with my headers or request body.
Please help me, as i am stuck with this from past 2 days.
Here is the full error message...
Error!!!Error #2096 (mx.messaging.messages::HTTPRequestMessage)#0
body = (Object)#1
FromDate = "01-01-2013 18:30"
Location = "String content"
LocationId = 2147483647
ReportId = 9223372036854776000
ReportName = "String content"
Team = "17,22,30,1,40,53,55,69,70,73,77"
TeamId = 2147483647
ToDate = "01-01-2013 18:30"
clientId = (null)
contentType = "application/json"
destination = "DefaultHTTP"
headers = (Object)#2
DSEndpoint = "direct_http_channel"
httpHeaders = (Object)#3
Content-Length = 347
Host = "192.168.11.59:3333"
messageId = "C130487E-0EBA-375E-E71D-A580EFE175EE"
method = "POST"
recordHeaders = false
timestamp = 0
timeToLive = 0
url = "my url"
You may need to check if the content of the parameters contains illegal characters like '<' or '>'. Replacing them with '& l t ;' or '& g t ;' (without spaces) may solve the problem.
Errors may occur when HttpService sends or receives strings including these two marks.
Using URLRequest would be a better choice since it would be free from this problem.

I want to know how calculate that start date(datefield) is less than always from end date(datefield) in flex?

I have a form in which i add two dates
Start date
End Date
I want to know how i validate that the selected start date is always less than end date(actually an expiry date).
You can do some thing like this to compare the dates,
trace(validateDate(new Date(2008, 5, 1), new Date(2008, 6, 1)));
protected function validateDate(date1:Date, date2:Date):Boolean
{
return (date1.time < date2.time);
}
You look some thing like this.Try This function:
public function compare (Start_date: Date, End_Date : Date) : Number
{
var Start_date1 : Number = Start_date.getTime ();
var End_Date1 : Number = End_Date.getTime ();
if (Start_date1 > End_Date1)
{
result = 0;
}
else
{
result = 1;
}
return result;
}
Small sample
<mx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.utils.ObjectUtil;
import mx.events.CalendarLayoutChangeEvent;
private function compareDate():void {
var fromDateFormat:String = DateField.dateToString(new Date(fromDates.selectedDate), "YYYY/MM/DD");
var toDateFormat:String = DateField.dateToString(new Date(toDates.selectedDate), "YYYY/MM/DD");
var todayDateStr:String = DateField.dateToString(new Date(), "YYYY/MM/DD");
var fromDate:Date = DateField.stringToDate(fromDateFormat, "YYYY/MM/DD");
var toDate:Date = DateField.stringToDate(toDateFormat, "YYYY/MM/DD");
var todayDate:Date = DateField.stringToDate(todayDateStr, "YYYY/MM/DD");
if(ObjectUtil.dateCompare(todayDate , fromDate) >= 0 && ObjectUtil.dateCompare(todayDate , toDate) <=0){
Alert.show("Valid");
}else{
Alert.show("InValid");
}
}
]]>
</mx:Script>
<mx:DateField id="fromDates"/>
<mx:DateField id="toDates"/>
<mx:Button id="checkValidity" click="compareDate()"/>
</mx:Application>
or
check the below link for validation
http://www.iamboredsoiblog.eu/flexfiles/start_end_date_check/srcview/index.html
you can directly use two dataFields and desable the end dateField date less than start dateField
you can do like this
<mx:DateField id="stDate"/>
<mx:DateField id="endDate" selectableRange="{{rangeStart: stDate.selectedDate}}"/>
from above you need not to compare the end date with start date... because dated less than start date will not be enable in end dateField..