Flex: assigning events to dynamically created buttons - apache-flex

Thanks to wezzy and the others who helped me out the past couple of days. I've been taking their advice and trying to figure the rest out on my own but I'm stuck again.
I have a txt file structured like this:
button1_label
button2_label
button3_label
My program creates these 3 buttons at runtime and places them in a group.
protected function onLoaded(e:Event):void {
var myArrayOfLines:Array = e.target.data.split(/\n/);
var tempBtn:Button;
for(var i:Number = 0;i < myArrayOfLines.length;i++){
var j:Number = i+1;
tempBtn = new Button();
tempBtn.id = "btn" + i;
tempBtn.addEventListener(MouseEvent.CLICK, function(evt:MouseEvent):void{
var index:uint = parseInt(evt.currentTarget.id.replace("btn", ""));
//TextArea code will go here
trace(text); // Traces null
});
tempBtn.label = myArrayOfLines[i];
btnArray.push(tempBtn);
group.addElement(btnArray[i]);
}
}
Now what you can see from my code is that I'm attempting to make each button print a string to a textarea. I've structured my new buttons.txt like this:
button1_label
"Hello"
button2_label
"Goodbye"
button3_label
"Come again"
So what I want to do is have button1 print "Hello". All the lines of the .txt file are pushed into myArrayOfLines. Thanks in advance for any help.
EDIT
Full explanation
Sorry I was trying to simplify my question, guess I made it harder to understand. I made a text editor than runs client side, no server. I have a set of buttons that insert predefined phrases into the TextArea Each button has a listener that does myTextArea.insert("sometext"); (but different text for each button. Users have requested the ability to create their own buttons to insert there own strings. I figured I would have a couple og textinputs where a user could define a label, and a String that would be inserted into the textarea on button click. I would write the label to one line, then the String to the next line. Right now I created a buttons.txt file with this format to see if it would work.
FINAL EDIT: WORKING CODE
public function setupBtns(e:Event):void{
var file:File = File.documentsDirectory.resolvePath("buttons.txt");
var stream:FileStreamWithLineReader = new FileStreamWithLineReader();
stream.open(file, FileMode.READ);
while(stream.bytesAvailable) {
// this line contains the headers like button1_label etc.
var label:String;
// this line contains the string
if(stream.bytesAvailable) {
// this line contains the actual label like "Hello";
label = stream.readUTFLine();
line = stream.readUTFLine();
// strip off the first and last character as they are double quotes
line = line.substring(1, line.length-1);
var tempBtn:Button = new Button();
tempBtn.addEventListener(MouseEvent.CLICK, btnListener);
tempBtn.label = label;
tempBtn.name = line;
btnArray.push(tempBtn);
for(var i:Number = 0;i<btnArray.length;i++){
group.addElement(btnArray[i]);
}
}
}
}
protected function btnListener(e:MouseEvent):void{
mainTextField.insertText(e.target.name);
trace(e.target.name);
}

Try this out and let me know how it works out...
EDIT: (try new code below)
protected function onLoaded(e:Event):void {
var myArrayOfLines:Array = e.target.data.split(/\n/);
var tempBtn:Button;
for(var i:Number = 0;i < myArrayOfLines.length;i=i+1){
var j:Number = i+1;
tempBtn = new Button();
tempBtn.id = "btn" + i;
tempBtn.addEventListener(MouseEvent.CLICK, function(evt:MouseEvent):void{
myTextArea.text += '\n' + myArrayOfLines[j];
});
tempBtn.label = myArrayOfLines[i];
btnArray.push(tempBtn);
group.addElement(btnArray[btnArray.length-1]);
}
}

first: don't use anonymous functions as listeners in actionscript - if you yo, you can't remove them later on.
instead use a class method like this:
tempBtn.addEventListener(MouseEvent.CLICK, onMouseClick);
private function onMouseClick(evt:MouseEvent):void
{
if (evt.currentTarget == button1_label)
{
// do sth for btn1
}
else if (evt.currentTarget == button2_label)
{
// do sth for btn2
}
// ...
}
edit
just saw, that you are using IDs, then just change the above code to sth like this:
if (evt.currentTarget.id == "btn1")

Related

Using a dropdown list to get image names from a folder and applying them to an image url

I'm trying to apply the name of the image but the images are not loading.
if (!IsPostBack)
{
string[] str = new string[] { "Select", "Anniversary", "Birthday",
"Graduation", "Sympathy" };
for (int i = 0; i < str.Length; i++)
{
DDl1.Items.Add(str[i]);
} // this Loop creates the items in the drop down list
{
string str = DDl1.Text;
Image1.ImageUrl="~/Media"+str+".png";
} // This is how i was trying to call the images from the Media folder in my project
change this
Image1.ImageUrl="~/Media"+str+".png";
to
Image1.ImageUrl="~/Media/"+str+".png";
Create an event OnSelectedIndexChanged on your <asp:DropDownList> and add AutoPostBack="True".
In Code behind event OnSelectedIndexChanged put the code as below:
string str = DDl1.Text; or string str = DDl1.SelectedText;
Image1.ImageUrl="~/Media/"+str+".png";
I hope this would help you.

How to browse to the next page in a datasource that is loaded into table in Google AppMaker

I'm working on a requirement where I have a datasource named 'emailSearchResults' where I search for email messages metadata and load the results in the datasource.
The fields in the datasource are not relevant, however I set the datasource to have 50 records per page as per the below screenshot:
The script I used to load the datasource is shown in the query field, that call the following script:
function getMessageDetails(userId, msgID)
{
var messageDetails = [];
var messageData;
var msgID_,subject_,from_,date_;
messageData=Gmail.Users.Messages.get(userId,msgID,{format:"metadata", metadataHeaders:["Message-ID", "Subject", "From", "Date"]});
console.log(messageData.payload.headers);
//console.log(msgID);
//console.log(messageData.payload.headers[3].value);
date_="<na>";
from_="<na>";
subject_="<na>";
msgID_="<na>";
for (var counter =0;counter<4;counter++)
{
if (messageData.payload.headers[counter].name=="Message-ID")
{
msgID_=messageData.payload.headers[counter].value;
}
if (messageData.payload.headers[counter].name=="Subject")
{
subject_=messageData.payload.headers[counter].value;
}
if (messageData.payload.headers[counter].name=="From")
{
from_=messageData.payload.headers[counter].value;
}
if (messageData.payload.headers[counter].name=="Date")
{
date_=messageData.payload.headers[counter].value;
}
}
messageDetails.push(date_);
messageDetails.push(from_);
messageDetails.push(subject_);
messageDetails.push(msgID_);
return messageDetails;
}
function searchMessages(userId,condition)
{
//
// first we build the conditions
// we can make it fixed
// or we can make it dynamic
var searchResult;
var deleteResult;
var currentMessage;
var results = [];
var pageToken;
var params = {};
var _stat;
var options = {
includeSpamTrash: "true",
pageToken: pageToken
};
var msgRecord = [];
do
{
searchResult=Gmail.Users.Messages.list(userId,options);
for (var i = 0; i < searchResult.messages.length; i++)
{
var record=app.models.emailSearchResults.newRecord();
msgRecord=getMessageDetails(userId,searchResult.messages[i].id);
record.msgMainID=searchResult.messages[i].id;
record.msgID=msgRecord[3];
record.subject=msgRecord[2];
record.senderAddress=msgRecord[1];
record.msgDate=msgRecord[0];
/*console.log(searchResult.messages[i].id);
console.log(msgRecord[3]);
console.log(msgRecord[2]);
console.log(msgRecord[1]);
console.log(msgRecord[0]);
return;*/
results.push(record);
msgRecord=null;
}
if (searchResult.nextPageToken) {
options.pageToken = searchResult.nextPageToken;
}
} while (searchResult.pageToken);
searchResult=null;
return results;
}
On the main page I put a table and linked it to the datasource, and I enabled pagination on the table, so I get the pager buttons at the bottom of the table as below:
When I execute the app and the datasource is filled, I see the first page results in a correct way, however when I want to move to the next page, I click the next page button and once the loading is complete I find out that I still see the same results from the first page on the table.
I am not familiar with how to make the table show the results of the second page then the third page, and I am going in circles on this...
Hope the explanation is clear and addresses the issue..
I would really appreciate any help on this!
Regards
Currently pagination isn't working as expected with calculated datasources. You can, however, build your own. There are several changes you'll need to make to accomplish this. First you'll want to refactor your searchMessages function to something like this:
function searchMessages(userId, pageToken){
var results = [];
var options = {
includeSpamTrash: "true",
pageToken: pageToken,
maxResults: 50
};
var searchResult = Gmail.Users.Messages.list(userId, options);
for (var i = 0; i < searchResult.messages.length; i++){
var record = app.models.emailSearchResults.newRecord();
var msgRecord = getMessageDetails(userId,searchResult.messages[i].id);
record.msgMainID = searchResult.messages[i].id;
record.msgID = msgRecord[3];
record.subject = msgRecord[2];
record.senderAddress = msgRecord[1];
record.msgDate = msgRecord[0];
results.push(record);
}
return {records: results, nextPageToken: searchResult.nextPageToken};
}
Then you'll want to change your datasource query. You'll need to add a number parameter called page.
var cache = CacheService.getUserCache();
var page = query.parameters.page || 1;
var pageToken;
if(page > 1){
pageToken = cache.get('pageToken' + page.toString());
}
var results = searchMessages('me', pageToken);
var nextPage = (page + 1).toString();
cache.put('pageToken' + nextPage, results.nextPageToken);
return results.records;
You'll need to modify the pagination widget's various attributes. Here are the previous/next click functions:
Previous:
widget.datasource.query.pageIndex--;
widget.datasource.query.parameters.page = widget.datasource.query.pageIndex;
widget.datasource.load();
Next:
widget.datasource.query.pageIndex++;
widget.datasource.query.parameters.page = widget.datasource.query.pageIndex;
widget.datasource.load();
You should be able to take it from there.

actionscript 2 functions for detecting when no keys are pressed

I would like to know how to detect when no buttons are pressed on a movieclip,
such as
if (no keys are pressed){
this.gotoAndStop("idle");
}
Firstly if you expand your question as you expand your purpose of what you achieve, maybe I can present a more in depth solllution ... ;) I can not imagine why you need a no buttons pressed event. Anyway you can use this code snippet.
//This belongs to no button pressed event.
var def = 0;
var keyListener:Object = new Object();
keyListener.onKeyDown = function() {
def = 1;
};
keyListener.onKeyUp = function() {
def = 0;
};
Key.addListener(keyListener);
//First Part for the whole movie clip
_root.onEnterFrame = function (){
trace(def);
if(def == 1){
this.gotoAndStop("idle");
}
}

call inline function and pass in current item as the argument - Flex 3

Im trying to create a loop of items like this...
for each (var btn:Object in ViewButtonData)
{
// build element
var box:HBox = new HBox();
box.styleName = "lefttab";
box.width = "100%";
box.addEventListener("rollOver", HoverTab(btn.id, 1));
box.addEventListener("rollOut", HoverTab(btn.id, 0));
// add element to list
}
I would like to pass in current HBox to the 'HoverTab' function. Is there a way to do that?
James Ward's comment is correct. You can just do:
function myHandler(event:Event):void {
var myHBox:HBox = event.currentTarget as HBox;
}
That said, the answer to your question is:
box.addEventListener("rollOver", function(e:Event) { HoverTab(box, btn.id, 1); });
..spread out for more readability:
box.addEventListener("rollOver",
function(e:Event) {
HoverTab(box, btn.id, 1);
}
);
The HBox should automatically be available in the event handler via event.currentTarget.
box.addEventListener("rollOver", hoverTab(btn.id, 1));
box.addEventListener("rollOut", hoverTab(btn.id, 0));
This won't work unless hoverTab is a function that returns a function that takes an event as its sole argument. Replace it with:
box.addEventListener("rollOver", hoverTab);
box.addEventListener("rollOut", rollOutTab);
And as James mentioned, you'll get HBox from event.currentTarget
function hoverTab(event:MouseEvent):void
{
var box:HBox = HBox(event.currentTarget);
}
To get btn.id inside hoverTab, store HBoxes and btn.ids into two arrays from the for-each loop. Now you can get the index of HBox using indexOf method - btn.id will be at the same index in its array.
var boxes:Array = [];
var ids:Array = [];
for each (var btn:Object in ViewButtonData)
{
// build element
var box:HBox = new HBox();
boxes.push(box);
ids.push(btn.id);
box.addEventListener(MouseEvent.ROLL_OVER, hoverTab);
box.addEventListener(MouseEvent.ROLL_OUT, rollOutTab);
// add element to list
}
function hoverTab(event:MouseEvent):void
{
var box:HBox = HBox(event.currentTarget);
var btnid:Number = ids[boxes.indexOf(box)];
}
Alternatively, (since ActionScript allows different types in the same array), you can push them into the same array and read the btn.id as array[array.indexOf(box) + 1]

Create HTML table out of object array in Javascript

I am calling a web Method from javascript. The web method returns an array of customers from the northwind database. The example I am working from is here: Calling Web Services with ASP.NET AJAX
I dont know how to write this javascript method: CreateCustomersTable
This would create the html table to display the data being returned. Any help would be appreciated.
My javascript
function GetCustomerByCountry() {
var country = $get("txtCountry").value;
AjaxWebService.GetCustomersByCountry(country, OnWSRequestComplete, OnWSRequestFailed);
}
function OnWSRequestComplete(results) {
if (results != null) {
CreateCustomersTable(results);
//GetMap(results);
}
}
function CreateCustomersTable(result) {
alert(result);
if (document.all) //Filter for IE DOM since other browsers are limited
{
// How do I do this?
}
}
else {
$get("divOutput").innerHTML = "RSS only available in IE5+"; }
}
My web Method
[WebMethod]
public Customer[] GetCustomersByCountry(string country)
{
NorthwindDALTableAdapters.CustomersTableAdapter adap =
new NorthwindDALTableAdapters.CustomersTableAdapter();
NorthwindDAL.CustomersDataTable dt = adap.GetCustomersByCountry(country);
if (dt.Rows.Count <= 0)
{
return null;
}
Customer[] customers = new Customer[dt.Rows.Count];
for (int i = 0; i < dt.Rows.Count; i++)
{
NorthwindDAL.CustomersRow row = (NorthwindDAL.CustomersRow)dt.Rows[i];
customers[i] = new Customer();
customers[i].CustomerId = row.CustomerID;
customers[i].Name = row.ContactName;
}
return customers;
}
Try to look what is the result variable value in debug mode. If the structure seems the structure that i'm imagining, something like this could work:
function CreateCustomersTable(result) {
var str = '<table>';
str += '<tr><th>Id</th><th>Name</th></tr>';
for ( var i=0; i< result.length; i++){
str += '<tr><td>' + result[i].CustomerId + '</td><td>' + result[i].Name + '</td></tr>';
}
str += '</table>';
return str;
}
And then You can do somethig like this:
var existingDiv = document.getElementById('Id of an existing Div');
existingDiv.innerHTML = CreateCustomersTable(result);
I wish this help you.
Something like this, assuming you have JSON returned in the "result" value. The "container" is a div with id of "container". I'm cloning nodes to save memory, but also if you wanted to assign some base classes to the "base" elements.
var table = document.createElement('table');
var baseRow = document.createElement('tr');
var baseCell = document.createElement('td');
var container = document.getElementById('container');
for(var i = 0; i < results.length; i++){
//Create a new row
var myRow = baseRow.cloneNode(false);
//Create a new cell, you could loop this for multiple cells
var myCell = baseCell.cloneNode(false);
myCell.innerHTML = result.value;
//Append new cell
myRow.appendChild(myCell);
//Append new row
table.appendChild(myRow);
}
container.appendChild(table);
You should pass the array as JSON or XML instead of just the toString() value of it (unless that offcourse is returns either JSON oR XML). Note that JSOn is better for javascript since it is a javascript native format.
Also the person who told you that browser other then IE can not do DOM manipulation should propably have done horrible things to him/her.
If your format is JSON you can just for-loop them and create the elements and print them. (once you figured out what format your service returns we can help you better.)

Resources