facebook actionscript graph api - using request_ids to retrieve users - actionscript-3

If I have used Facebook.ui() to allow the user to select a bunch of their friends, how can I use the returned request_ids array to access the friends /feeds please?
I've tried the following:
Facebook.ui("apprequests", { message:"select some friends" }, handleAppRequest, "iframe");
which allows the selection of friends to tell about the app. I then do the following:
private function handleAppRequest(result:Object):void
{
Debug.logObject(result, this, "handleAppRequest");
for (var i:int = 0; i < result.request_ids.length; i++)
{
var requestID:String = result.request_ids[i];
Facebook.api("/" + requestID, handleRequestFriends);
}
}
to select the friends returned in the result object (which I think might be where I'm going wrong), and then this returns a fail:
private function handleRequestFriends(success:Object, fail:Object):void
{
if (success) trace("success");
else trace(fail);
}
Thanks in advance
ob
EDIT: (new users can't answer their own question)
Hey again Michiel
ah i got it
it should be the following:
Facebook.ui("apprequests", { message:"select some friends" }, handleAppRequest, "iframe");
private function handleAppRequest(result:Object):void
{
for (var i:int = 0; i < result.request_ids.length; i++)
{
var requestID:String = result.request_ids[i];
Facebook.api("/" + requestID, handleRequestFriends);
}
}
private function handleRequestFriends(success:Object, fail:Object):void
{
if (success)
{
var values:Object =
{
access_token:Facebook.getSession().accessToken,
name:"This is my title",
link:"http://example.com",
picture:"http://example.com/facebook/facebooktutorial/canvas/images/icon-75x75.gif",
caption:"this is a caption",
message:"This is a test message on " + new Date().toString()
};
var friendID:String = success.to.id;
Facebook.api("/" + friendID + "/feed", handleSubmitFeed, values, URLRequestMethod.POST);
}
else
{
Debug.logObject(fail, this, "handleRequestFriends");
}
}
One question tho - can i use the facebook friend selector and just return the results without the apprequest firing off to them?
thanks
ob

i would again suggest that you use the params to send your access_token, like in your previous question :)
private function handleAppRequest(result:Object):void
{
Debug.logObject(result, this, "handleAppRequest");
for (var i:int = 0; i < result.request_ids.length; i++)
{
var requestID:String = result.request_ids[i];
var _params:Object = new Object();
_params.access_token = Facebook.getSession().accessToken;
Facebook.api("/" + requestID, handleRequestFriends, _params, "GET");
}
}
and i assume you are trying to get the user, because if you want to post to their feed, you should just use
var _params:Object = new Object();
_params.access_token = Facebook.getSession().accessToken;
_params.message = _message;
Facebook.api("/" + requestID + "/feed", handleRequestFriends, _params, "POST");
edit: btw: are you sure you are getting the right id's with this method? (haven't accessed friends list before, so i have no idea).

Related

Unable to get this "tagging unanswered email" script to work

The following is a script that I found online to tag all the unanswered emails. It works for one of my gmail accounts, however when I shared it to another account and run it, it returns nothing every single time, even though there are unanswered emails within that time range. I then tried copy and paste the codes into a new project, however still wouldn't work.
Anyone has any ideas?
Thanks in advance!
/*
* This script goes through your Gmail Inbox and finds recent emails where you
* were the last respondent. It applies a nice label to them, so you can
* see them in Priority Inbox or do something else.
*
* To remove and ignore an email thread, just remove the unrespondedLabel and
* apply the ignoreLabel.
*
* This is most effective when paired with a time-based script trigger.
*
* For installation instructions, read this blog post:
* http://jonathan-kim.com/2013/Gmail-No-Response/
*/
// Edit these to your liking.
var unrespondedLabel = 'No Response',
ignoreLabel = 'Ignore No Response',
minDays = 0.125,
maxDays = 5;
function main() {
processUnresponded();
cleanUp();
}
function processUnresponded() {
var threads = GmailApp.search('is:sent from:me -in:chats older_than:' + minDays + 'd newer_than:' + maxDays + 'd'),
numUpdated = 0,
minDaysAgo = new Date();
minDaysAgo.setDate(minDaysAgo.getDate() - minDays);
// Filter threads where I was the last respondent.
for (var i = 0; i < threads.length; i++) {
var thread = threads[i],
messages = thread.getMessages(),
lastMessage = messages[messages.length - 1],
lastFrom = lastMessage.getFrom(),
lastMessageIsOld = lastMessage.getDate().getTime() < minDaysAgo.getTime();
if (isFromMe(lastFrom) && lastMessageIsOld && !threadHasLabel(thread, ignoreLabel)) {
markUnresponded(thread);
numUpdated++;
}
}
Logger.log('Updated ' + numUpdated + ' messages.');
}
function isFromMe(fromAddress) {
var addresses = getEmailAddresses();
for (i = 0; i < addresses.length; i++) {
var address = addresses[i],
r = RegExp(address, 'i');
if (r.test(fromAddress)) {
return true;
}
}
return false;
}
function getEmailAddresses() {
var me = Session.getActiveUser().getEmail(),
emails = GmailApp.getAliases();
emails.push(me);
return emails;
}
function threadHasLabel(thread, labelName) {
var labels = thread.getLabels();
for (i = 0; i < labels.length; i++) {
var label = labels[i];
if (label.getName() == labelName) {
return true;
}
}
return false;
}
function markUnresponded(thread) {
var label = getLabel(unrespondedLabel);
label.addToThread(thread);
}
function getLabel(labelName) {
var label = GmailApp.getUserLabelByName(labelName);
if (label) {
Logger.log('Label exists.');
} else {
Logger.log('Label does not exist. Creating it.');
label = GmailApp.createLabel(labelName);
}
return label;
}
function cleanUp() {
var label = getLabel(unrespondedLabel),
iLabel = getLabel(ignoreLabel),
threads = label.getThreads(),
numExpired = 0,
twoWeeksAgo = new Date();
twoWeeksAgo.setDate(twoWeeksAgo.getDate() - maxDays);
if (!threads.length) {
Logger.log('No threads with that label');
return;
} else {
Logger.log('Processing ' + threads.length + ' threads.');
}
for (i = 0; i < threads.length; i++) {
var thread = threads[i],
lastMessageDate = thread.getLastMessageDate();
// Remove all labels from expired threads.
if (lastMessageDate.getTime() < twoWeeksAgo.getTime()) {
numExpired++;
Logger.log('Thread expired');
label.removeFromThread(thread);
iLabel.removeFromThread(thread);
} else {
Logger.log('Thread not expired');
}
}
Logger.log(numExpired + ' unresponded messages expired.');
}
The Gmail search operator "older_than" does not support decimals, so you cannot use "0.125" in this case. Make sure you use an integer number/day. The script will not return errors, but the search will not work. More info about the Gmail search operators at https://support.google.com/mail/answer/7190?hl=en

Simple autocomplete with Ace Editor in AS3?

I'm working in XML and I'd like to provide autocomplete suggestions for the attributes for specific node types using AS3.
For example, if the user is has a cursor in the following node:
<s:Button label="Hello World"/>
I'd like autocomplete to show "width, height, x, y".
I'm trying to get the node name and namespace and then give the editor a list of attributes that should appear in autocomplete.
I found similar questions but those are using a service call and a few that are out dated. I may delete this question if it is a duplicate.
Ace Editor for AS3 here.
In my case, for AS3, it is a combination of items:
ace.setCompleters(null); // I'm removing existing autocomplete
ace.addCompleter(codeCompleter); // adding my own
public var autoCompleteErrorMessage:String = "Nothing available";
public function codeCompleter(editor:Object, session:Object, position:Object, prefix:String, callback:Function):void {
var row:int = position.row;
var column:int = position.column;
/*
if (prefix.length === 0) {
callback(null, []);
return;
}
*/
//var myList:Array = {value: "message", caption: "Caption to user", meta: "Type shown", score: "I don't know"};
var testing:Boolean = false;
if (testing) {
callback(autoCompleteErrorMessage, [{value:"addedToStage"},{value:"added"},{value:"adding"}]);
}
else {
callback(autoCompleteErrorMessage, attributes);
}
}
protected function cursorChangeHandler(event:Event):void {
var qname:QName = getQNameFromCursorPosition(ace.row, ace.column);
if (qname==null) {
if (attributes.length) {
attributes = [];
}
return;
}
if (qname) {
attributes = getSuggestionListFromObject(classObject);
autoCompleteErrorMessage = null;
lastSelectedQName = qname;
}
}
public static var XML_TAG_NAME:String = "meta.tag.tag-name.xml";
public static var XML_TAG_OPEN:String = "meta.tag.punctuation.tag-open.xml";
public static var XML_TAG_CLOSE:String = "meta.tag.punctuation.tag-close.xml";
public static var XML_ATTRIBUTE_NAME:String = "entity.other.attribute-name.xml";
public function getQNameFromCursorPosition(row:int, column:int):QName {
var token:Object;
var line:String;
var type:String;
var value:String;
var found:Boolean;
var qname:QName;
for (; row > -1; row--) {
line = ace.getLine(row);
column = line.length;
for (; column>-1; column--) {
token = ace.getTokenAt(row, column);
type = token ? token.type : "";
if (type==XML_TAG_NAME) {
value = token.value;
found = true;
}
}
if (found) break;
}
if (found) {
qname = new QName("", value);
}
return qname;
}
The getQNameFromCursorPosition() method is fragile and I'm looking into a new method using the jumpToMatching() method.

AS3 many buttons with boolean function - less verbose?

I have twenty eight instances of a two-frame MovieClip (frame1 = off - frame 2 = on) to select PDFs to send. The following code works fine, but I am looking to tighten it up and make it less verbose and easier to read. I include only one reference to an instance for space and sanity sake.
function PDFClick(e:MouseEvent):void {
targetPDF = e.target.ID;
trace("targetPDF " +targetPDF);
if (targetPDF == "PDF1")
if (pdf.pcconnectionPDF1.currentFrame == 1)
{
pdf.pcconnectionPDF1.gotoAndPlay(2);
PDF1 = 1;
trace("PDF1 is "+PDF1);
}else{
pdf.pcconnectionPDF1.gotoAndPlay(1);
PDF1 = 0;
trace("PDF1 is "+PDF1);
}
Thanks! trying to learn
You'll want to generalize your calls to your ID, that way you don't need special code for each condition.
function PDFClick(e:MouseEvent):void {
var ID:String = e.target.ID;
var mc = pdf["pcconnection" + ID];
if (mc.currentframe == 1) {
mc.gotoAndPlay(2);
this[ID] = 1;
} else {
mc.gotoAndPlay(1);
this[ID] = 0;
}
}
How about this:
function PDFClick(e:MouseEvent):void {
targetPDF = e.target.ID;
trace("targetPDF " +targetPDF);
if (targetPDF == "PDF1") {
var frame:int = pdf.pconnectionPDF1.currentFrame;
pdf.pconnectionPDF1.gotoAndPlay( frame == 1 ? (PDF1 = 1)+1 : (PDF1 = 0)+1 );
}
}
I think that's about what you are looking for.

Trying to create a function which extracts a URL from an array. JavaScript

So basically I would like to create a function that when alerted, returns the URL from an array (in this case the array is declared as 'websites'). The function has two parameters 'websites' and 'searchTerm'.
I'm struggling to make the function behave, so that when i type yahoo or google or bing in the searchTerm parameter for the function; I want it to return the corresponding URL.
Any help or support would be greatly appreciated.
Sorry if I have not made myself clear in my explanation, if this is the case, let me know and I will try and be clearer in my explanation.
Thanks in advance!
Try something more like:
var websites = {google: 'www.google.com', yahoo: 'www.yahoo.com'};
function filterURL(websites,searchTerm)
{
return websites[searchTerm] || 'www.defaultsearchwebstirehere.com';
}
** Update following comment **
Build up your websites object like so (where input is your array of key values seperated by pipe characters):
var websites = {};
for (var i = 0; i < input.length; i++) {
var siteToSearchTerm = input[i].split('|');
websites[siteToSearchTerm[1]] = siteToSearchTerm[0];
}
Here is how:
var websites = ["www.google.com|Google" , "www.yahoo.com|Yahoo" , "www.bing.com|Bing"];
function filterURL(websites,searchTerm)
{
for (var i = 0; i < websites.length; i++) {
if (websites[i].split('|')[1] === searchTerm) {
return websites[i].split('|')[0];
}
}
}
Working Example
You can also validate and improve function:
function filterURL(websites,searchTerm)
{
if (typeof websites != 'Array' || ! searchTerm) return false;
for (var i = 0; i < websites.length; i++) {
if (websites[i].split('|')[1] === searchTerm) {
return websites[i].split('|')[0];
}
}
return false;
}
Why not just use an object?
var websites = {
Google: 'www.google.com',
Yahoo: 'www.yahoo.com'
};
function filterURL(sites, searchTerm) {
if (sites[searchTerm]) {
return sites[searchTerm];
} else {
// What do you want to do when it can't be found?
}
}
alert(filterURL(websites, 'Google')); // alerts 'www.google.com'
You should really be using a hash-table like structure so that you don't have to search through the whole array every time. Something like this:
var websites = {
"Google": "www.google.com",
"Yahoo": "www.yahoo.com",
"Bing": "www.bing.com"
};
function filterURL(websites, searchTerm) {
if (websites[searchTerm] !== undefined)
return websites[searchTerm];
else
return null;
}
I'm not sure why you want to use an array for this, as what you're really doing fits a key-value pair better; however, here's how I'd do it:
function filterURL(websites, searchTerm) {
var i = 0,
parts;
for (i = 0; i < websites.length; i++) {
parts = websites[i].split("|");
if (parts[1].toLowerCase() === searchTerm) {
return parts[0];
}
}
}
But consider if you used a proper JavaScript Object instead:
var websites = {
Google: "www.google.com",
Yahoo: "www.yahoo.com",
Bing: "www.bing.com"
}
// Now it's much simpler:
function filterURL(websites, searchTerm) {
// key has first letter capitalized…
return websites[searchTerm.charAt(0).toUpperCase() + searchTerm.slice(1).toLowerCase()];
}

Scroll to alphabet in a List (ArrayCollection dataProvider) (Alphabet Jump)

Hopefully this is easy but that sometimes means its impossible in flex and I have searched quite a bit to no avail.
Say I have a list (LIST#1) of artists:
2Pac
Adele
Amerie
Beyonce
Jason Aldean
Shakira
The Trews
I also have a list (LIST#2) that has the values #,A-Z - how would I create an alphabet jump?
So If a user clicked on "A" in LIST#2 that would automatically scroll to "Adele" at the top of LIST#1 - not filter so he/she could scroll up to view 2Pac or down to view The Tews if they were not in the view yet.
Its a standard Flex Spark List with an ArrayCollection as the dataProvider - the artist field is called: "title" along with a unique id field that is not visible to the user.
Thanks!
Please see comments on marker answer for discussion on Dictionary that may be faster in some cases. See below for code (HAVE NOT CONFIRMED ITS FASTER! PLEASE TEST):
private function alphabet_listChange(evt:IndexChangeEvent) : void {
var letter:String;
letter = evt.currentTarget.selectedItems[0].toString();
trace(currentDictionary[letter]);
ui_lstLibraryList.ensureIndexIsVisible(currentDictionary[letter]);
}
public function createAlphabetJumpDictionary() : Dictionary {
//alphabetArray is a class level array containing, A-Z;
//alphabetDictionary is a class level dictionary that indexes A-z so alphabetDictionary["A"] = 0 and ["X"] = 25
var currentIndexDict:Dictionary = new Dictionary; //Dictionary is like an array - just indexed for quick searches - limited to key & element
var searchArray:Array = new Array;
searchArray = currentArrayCollection.source; //currentArrayCollection is the main array of objects that contains the titles.
var currentIndex:Number; //Current index of interation
var currentAlphabetIndex:Number = 0; //Current index of alphabet
for (currentIndex = 0; currentIndex < searchArray.length; currentIndex++) {
var titleFirstLetter:String = searchArray[currentIndex].title.toString().toUpperCase().charAt(0);
if (titleFirstLetter == alphabetArray[currentAlphabetIndex]) {
currentIndexDict[titleFirstLetter] = currentIndex;
trace(titleFirstLetter + " - " + currentIndex);
currentAlphabetIndex++;
} else if (alphabetDictionary[titleFirstLetter] > alphabetDictionary[alphabetArray[currentAlphabetIndex]]) {
trace(titleFirstLetter + " - " + currentIndex);
currentIndexDict[titleFirstLetter] = currentIndex;
currentAlphabetIndex = Number(alphabetDictionary[titleFirstLetter] + 1);
}
}
return currentIndexDict;
}
private function build_alphabeticalArray() : Array {
var alphabetList:String;
alphabetList = "A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z";
alphabetArray = new Array;
alphabetArray = alphabetList.split(".");
return alphabetArray;
}
private function build_alphabetDictionary() : Dictionary {
var tmpAlphabetDictionary:Dictionary = new Dictionary;
for (var i:int=0; i < alphabetArray.length; i++) {
tmpAlphabetDictionary[alphabetArray[i]] = i;
trace(alphabetArray[i] + " - " + i);
}
return tmpAlphabetDictionary;
}
private function buildCurrentDictionary() : void {
trace("Collection Changed");
currentDictionary = new Dictionary;
currentDictionary = createAlphabetJumpDictionary();
}
The Flex Spark list has a very convenient method called ensureIndexIsVisible(index). Check the Flex reference documentation. All you have to do is to find the index of the first artist for the corresponding selected alphabet letter:
public function findAlphabetJumpIndex():Number
{
var jumpToIndex:Number;
var selectedLetter:String = alphabethList.selectedItem;
for (var i:int=0; i < artists.length; i++)
{
var artistName:String = artists.getItemAt(i);
var artistFirstLetter:String = artistName.toUpperCase().charAt(0);
if (artistFirstLetter == selectedLetter)
{
jumpToIndex = i;
break;
}
}
return jumpToIndex;
}
You can iterate your artist list data provider and check if artist name starts with selected alphabet from list two. When corresponding artist is found, set artist list selected index a value what you get from iterating data.