Flash and PHP

Specialiserings projekt af Jesper Friis (MMD)

Procesevaluering april 1, 2009

Arkiveret i: Uncategorized — jesperfriis @ 7:24 pm

Den måde jeg har lært mest på i dette projekt, er bl.a., at jeg har tvunget mig selv til at kommentere og forstå næsten al koden både AS3, PHP og MySQL.Jeg har også haft det udgangspunkt, at jeg selv skulle oploade applikationerne til enten min localhost eller egen webserver på nettet og få dem til at virke. På denne måde har jeg været tvunget til at arbejde med en MySQL database, min webserver samt forbindelsen mellem disse.Hvis jeg ikke har kunnet få noget til at virke, hvilket tit skete, undersøgte jeg det på forskellig vis indtil jeg fandt løsningen. Dette lærte jeg meget af, fordi jeg var tvunget til at forstå koden fuldt ud for at kunne lokalisere, hvor fejlen evt. kunne være.Men som man kan se og læse om, så har jeg alligevel ikke fået alle applikationer til at virke fuldt ud. Men det har så for det meste også været fordi, at jeg er stødt ind i nogle problemer, jeg ikke lige har haft overskud til at undersøge nærmere, da ville tage fokus væk fra det, jeg havde som udgangspunkt at undersøge. Det gode er jo at få en viden om, hvilke ting man så skal undersøge nærmere for at komme videre næste gang, når det er selve applikationen, der er i fokus.Jeg har selvfølgelig også lært meget af de beskrivelser og forklaringer, der har været af koden til applikationerne i bogen og den generelle beskrivelse af både AS3, PHP og MySQL. Men jeg har også lært meget ved at se tutorials, der beskriver koderne.Sidst har det også været godt at skulle skrive om projektet og videns dele mine erfaringer på en blog. Det har også været med til at jeg har skullet forstå tingene fuldt ud, før jeg kunne skrive om dem, samt at det har været med til, at jeg har skullet producere noget hver dag, så jeg kunne skrive om det på bloggen.Jeg synes det gode ved at følge en bog hele vejen, er at man gentager en masse øvelser igen og igen og derved forstår mere og mere, samtidig med at det selvfølgelig også bliver sværere og sværere, så man også lære noget nyt.

 

File editor (lille cms system!) marts 26, 2009

Arkiveret i: Uncategorized — jesperfriis @ 1:41 pm
I dag har jeg kigget på en “file editor” applikation. Det er også, hvad man måske kan kalde et meget lille CMS system (content managment system). Denne file editor lader dig ændre i en af de tre tekst filer og gemme det i en mappe på serveren. Næste gang man så loader filen, er den ændret. Dette foregår ved hjælp af  AS3 koden, der kalder et PHP script, der alt efter om man vil “loade” en fil eller “save” en ændring i teksten, henter den ønskede tekst fil i en tekst mappe, der selfølgelig også er at finde på serveren, og enten redigerer i den og sender den tilbage til Flash, eller bare sender den tibage, som den var.
Man har også mulighed for at “reset” det,  man har ændret i teksten, inden man trykker på “save” knappen. Dette foregår i AS3 koden, der “cacher” (opfanger og gemmer), den tekst der bliver skrevet i tekstfeltet.
I et større CMS system ville man normalt have langt flere funktioner at vælge mellem bl.a. en “delete” og “move” funktion, samt at der vil være mange flere muligheder end kun at rette og skrive tekst. Der skulle også være langt større sikkerhed omkring dataen, der bliver udvekslet mellem applikationen og serveren, samt et login system. Samtidig ville de fleste cms systemer gøre brug af en database til at opbevare de forskellige filer.
Det ville også være en god ide, at give brugeren besked, når system er i gang med at save og loade filer.
Men ved hjælp af denne lille applikation synes jeg, man får et godt billede af, hvordan man laver og bruger et sådan system, og samtidig også kan se de store fordele, der er ved, at brugeren selv kan opdatere indholdet i sin flash applikation.
Men som man nok kan regne ud, er det en større opgave at gå i gang med et rigtigt cms system!
File editoren kan ses og prøves på: http://jesperf.dk/flashandphp/file_editor/index.html
Og her kommer koden:
AS3:
//path to the php file
var phpFile:String = “http://jesperf.dk/flashandphp/file_editor/fileEditor.php”;
// and defining the variables to be used
var files:Array = ['sample.txt', 'anotherfile.txt', 'readme.txt'];
var storedFileData:String;

// responsible for populating the file list comboBox
function populateFileList():void
{

// by going through the “files” array
for(var i:uint=0; i < files.length; i++)
{

// add the items to the list using a for loop
fileListCombo.addItem({label:files[i], data:files[i]});
}
}
//The method loadFile is called when the loadbtn is clicked. this handler sets up a file request
// – with a file variable that PHP uses to load the actual file
function loadFile(e:MouseEvent):void
{

var variables:URLVariables = new URLVariables();
// the selected file from the list is sent to PHP as a variable request
variables.file = fileListCombo.selectedItem.data;

var urlRequest:URLRequest = new URLRequest(phpFile);
urlRequest.data = variables;

// loads the requested file from PHP
var urlLoader:URLLoader = new URLLoader();
// calls the fileLoaded function when the load is complete
urlLoader.addEventListener(Event.COMPLETE, fileLoaded);
urlLoader.load(urlRequest);
}


function fileLoaded(e:Event):void
{

var urlLoader:URLLoader = URLLoader(e.target);
var variables:URLVariables = new URLVariables(urlLoader.data);

// the loaded data is sent into the bodyTxt textArea
bodyTxt.text = unescape(variables.fileContents);
// – and also to the storedFileData variable
// this variable is used to cache the unmodified results.
// -You can revert to these results later by clicking the reset button
storedFileData = bodyTxt.text;
}

function resetHandler(e:MouseEvent):void
{

//this function simply replaces the text in the text area with the stored text
bodyTxt.text = storedFileData;
}

// the last function is responsible for saving the edited content.
// Before the data is saved, it is cached ,which eliminates the need to reload the data
function saveHandler(e:MouseEvent):void
{

// the text written is stored in the storedFileData variable
var body:String = bodyTxt.text;
storedFileData = body;

// calls PHP with the variables containing the action “save” and the bodyTxt
var variables:URLVariables = new URLVariables();
variables.file = fileListCombo.selectedItem.data;
variables.action = “save”;
variables.fileContents = body;

var urlRequest:URLRequest = new URLRequest(phpFile);
urlRequest.data = variables;

var urlLoader:URLLoader = new URLLoader();
urlLoader.load(urlRequest);
}

//the click on the different buttons calls the different functions
loadFileBtn.addEventListener(MouseEvent.CLICK, loadFile);
saveBtn.addEventListener(MouseEvent.CLICK, saveHandler);
resetBtn.addEventListener(MouseEvent.CLICK, resetHandler);

// calls the populateFileList function so the list is populated
populateFileList();

PHP’en:
<?phperror_reporting(0);

// check for valid file because whether you are saving or loading you need a valid file
// this application doesn’t have a delete og move action as you probably would in a bigger real world application
if(!empty($_GET['file']))
{

// path to the folder with the different files
$file = ‘./files/’ . $_GET['file'];

// the save action is responsible for loading the requested file, replacing the existing text, and finally resaving the file
// this example doesn’t focus on security so checking for valid characters and other security stuff is let out
if($_GET['action'] == ‘save’)
{

// the variable $fileContents is retrieved from the GET data sent by Flash
$fileContents = $_GET['fileContents'];

// the file  is loaded using fopen() with write access to overwrite
$handle = fopen($file, ‘w+’);
// once the file is loaded a call to fwrite() is made, which actually writes the content to the file and saves the file
fwrite($handle, $fileContents);
// last step of the save action is to close the file resource and free up teh memory
fclose($handle);
}

// the loading of a file is much easier. Just reference the file and load the contents using file_get_contents
// – which returns the entire file as a string
else
{
$loadedFile = file_get_contents($file);
print “fileContentsq=” . $loadedFile;
}
}

?>

 

Videoplayer marts 25, 2009

Arkiveret i: Uncategorized — jesperfriis @ 3:08 pm

Video afspillere bliver mere og mere populære eftersom, at internettet bliver hurtigere og hurtigere. Flash har en indbygget videoplayer component og ved hjlæp af denne og en ComboBox component har jeg i denne applikation lavet en video afspiller, der kommunikere med PHP som sender et XML objekt tilbage til swf. filen, som på denne måde ved, hvormange videoer der er at vælge imellem fra video listen, samt at den via XML’en kan finde ud af URL’en til netop den video, man vælger at se fra video listen. Man kan desværre kun se 1 video fra listen, da den ikke vil loade en ny. Men videoen er alligevel den samme allesammen, så det gør nok ikke så meget! Det ville den dog gerne på min localhost server, så endnu engang er det lidt mærkeligt, hvad der sker, når jeg uploader tingene på min rigtig server.

Applikationen kan ses her: http://jesperf.dk/flashandphp/video/index.html

Her kommer koden, først AS3:

package
{

// imports the nescesary classes
import flash.display.MovieClip;
import flash.events.*;
import flash.net.URLVariables;
import flash.net.URLRequest;
import flash.net.URLLoader;

import flash.media.Video;
public class VideoPlayer extends MovieClip
{

// the path to the pphp file
public var phpFile:String = “http://jesperf.dk/flashandphp/video/videoManager.php”;

// creates a variable to hold the videoplayer object. It uses the FLVPlayback class which are located in the library
private var _player:FLVPlayback;

public function VideoPlayer()
{

// sets the variable equal to the “player” instance on the stage
_player = this['player'];
// put an event listener to the videoListCombo instance(instance of ComboBox) on the stage and when its clicked it calls the comboHandler function
this['videoListCombo'].addEventListener(Event.CHANGE, comboHandler);

// calls the loadData function
loadData();
}

//calls the php file and loads the video data (urlvariables) which is returned in XML format
public function loadData():void
{

//
var urlVariables:URLVariables = new URLVariables;
// the request send along to php with the get method is “getvideos” which is send as the variable “a”
urlVariables.a = “getvideos”;

var urlRequest:URLRequest = new URLRequest(phpFile);
urlRequest.data = urlVariabl
es;

// when the data is fully loaded it calls the dataLoaded function
var urlLoader:URLLoader = new URLLoader();
urlLoader.addEventListener(Event.COMPLETE, dataLoaded);

urlLoader.load(urlRequest);
}

// this function makes the loaded XML inta a valid xml object for flash to work with
private function dataLoaded(e:Event):void
{

var urlLoader:URLLoader = URLLoader(e.target);
var xml:XML = new XML(urlLoader.data);
trace(xml);

//add an item to the “videoListCombo”‘s list
this['videoListCombo'].addItem({label:’Choose Video…’, data:1});
// going through the xml and adds the video items to the “videoListCombo”‘s list
for each(var item in xml..video)
{

// makes the variables to refer to when you click in the video list
var name:String = item..attribute(‘name’);
var src:String = item..attribute(‘src’);

// adds the variables to the list each time the loop goes through the xml
this['videoListCombo'].addItem({label:name, data:src});
}
}

private function comboHandler(e:Event):void
{

//only if a valid data value is found the video is loaded
if(e.target.selectedItem.data == -1) return;
// writes to the output panel which video you load
trace(“Load Video: ” + e.target.selectedItem.data);
//the string that specifies the URL of the FLV file to stream and how to stream it when you click an item in the list.
_player.source = ‘videos/’ + e.target.selectedItem.data;
}
}
}

Her PHP’en:

<?php

// this variable snaps the urlvariable send with the get method from flash if its set
$action = (isset($_GET['a']));

// the array of videos. Its a static array but one could easily use a MySQL database instead
$videos = array(
array(“Sample Video 1″, “color.flv”, 0),
array(“Sample Video 2″, “color.flv”, 0),

array(“Sample Video 3″, “color.flv”, 0),
array(“Sample Video 4″, “color.flv”, 0),
array(“Sample Video 5″, “color.flv”, 0),
array(“Sample Video 6″, “color.flv”, 0)
);

// if the urlvariable sent from flash is equal to “getvideos”
// – the video list is retrieved and a XML object is build to be passsed back to flash
if($action == “getvideos”)
{
$xml = “<videos>”;
for($i=0; $i < count($videos); $i++)
{
$xml .= “\t<video”;

$xml .= ” name=\”" . $videos[$i][0] . “\”";
$xml .= ” src=\”" . $videos[$i][1] . “\”";
$xml .= ” playCount=\”" . $videos[$i][2] . “\”";
$xml .= ” />\n”;
}
$xml .= “</videos>”;

//a header type of XML is outputted
header(“Content-type: text/xml”);
//output the XML code
print $xml;
}

?>

 

Gemme et billede fra en tegne applikation! marts 24, 2009

Arkiveret i: Uncategorized — jesperfriis @ 12:02 pm

I går og i dag har jeg siddet og bakset med at få tegneapplikationen til at gemme et png billede på serveren. Det lader sig faktisk også gøre på min localhost, men problemet er bare at billede,t der bliver gemt ikke registrerer nogle pixels farver. Den registrerer størrelsen på det billede, man tegner, og den genererer også den xml, der skal til , og som skal sendes videre til php. Det er funktionen “getPixel”, der skulle registrere de forskellige farver, men som ikke gør det. Jeg vil bruge lidt mere tid på at se, om jeg kan få det til at virke, og selv om det ikke lykkes, så vil jeg senere lige uploade den kode, der skal bruges for at lave applikationen.

Applikationen ser således ud : http://jesperf.dk/flashandphp/drawing1/index.html og tager udgangspunkt i en den tegne applikation og tilhørende kode jeg har  uploaded her på bloggen før. Men den virker som sagt ikke!!!

Koden der skal tilføjes til koden til tegneapplikationen som er beskrevet tidligere her på bloggen er følgende:

AS3 koden: ( det grå er noget af koden fra tegneapplikationen, så man ved hvor det skal sættes ind!)

var penMC:MovieClip;
var isDrawing:Boolean = false;
var penTipSize:uint = 1;
var penColor:Number = 0×0000
00;
// path to the php file
var phpFile:String = “http://localhost/flashandphp/DrawingGD/ImageGenerator.php”;

function init():void
{
penMC = new MovieClip();
stage.addEventListener(MouseEvent.MOUSE_DOWN, startDrawing);
stage.addEventListener(MouseEvent.MOUSE_UP, stopDrawing);
stage.addEventListener(MouseEvent.MOUSE_MOVE, drawing);

// when you click the generate image button you call the generateImage function
toolsMC.generateMC.addEventListener(MouseEvent.CLICK, generateImage);
addChild(penMC);

function generateImage(e:MouseEvent):void
{

// the variables used to determind the width and height of the image
var width:uint = penMC.width;
var height:uint = penMC.height;

// the buildingImageMC becomes visible when you’ve clicked the button
toolsMC.buildingImageMC.visible = true;

// building a new bitmap using the draw method of the BitmapData class
var bmp:BitmapData = new BitmapData(width, height, false, 0xFFFFFF);
// it takes one argument which is the target. The method takes the argument and copies the pixel data to the new bitmap
bmp.draw(penMC);
// after the new bitmap is created you can build a loop that will scan the bitmap and grap the color of each pixel
var xml:String = “<points>”;

for(var i:uint=0; i < width; i++)
{
for(var j:uint=0; j < height; j++)
{
var color:String = bmp.getPixel(i, j).toString(16);

if(color == “0″)
{
color = “00FF33″;
}

xml += “<point>”;
xml += “    <x>” + i + “</x>”;
xml += “    <y>” + j + “</y>”;
xml += “    <c>” +  color + “</c>”;
xml += “</point>”;
}

}

xml += “</points>”;
trace(xml);

// the color data is stored in a custom xml document that is sent of to php once the entire image is scanned
var urlVariables:URLVariables = new URLVariables();
urlVariables.width = width;

urlVariables.height = height;
urlVariables.pointData = xml;

var urlRequest:URLRequest = new URLRequest(phpFile);
urlRequest.method = URLRequestMethod.POST;
urlRequest.data = urlVariables;

// the sendToURL is used when you don’t expect to get something back from php

sendToURL(urlRequest);

}

function imageGenerated(e:Event):void
{

// when the image is generated the “building image” text is removed
toolsMC.buildingImageMC.visible = false;
}

<?php
// the width,cheight and xml are all passed using post data because a get request would fail
$width = $_POST['width'];
$height = $_POST['height'];

// makes an xml object that is used to generate or render the final image
$points = simplexml_load_string($_POST['pointData']);

// when the data is properly loaded you set up the base for the rendered image using imagecreatetruecolor function which is part of the GD library
$img = imagecreatetruecolor($width, $height);

// the actual image is generated by looping through all of the xml data that is pulling out the color values that was captured in flash
$limit = count($points->point);

for($j=0; $j < $limit; $j++)
{
$x = $points->point[$j]->x;
$y = $points->point[$j]->y;

$color = $points->point[$j]->c;
$color = hexdec($color);

// all of the data is passed to the imagesetpixel function on each pass of the inner loop
imagesetpixel($img, $x, $y, $color);
}

// render the image as png and save it to the file system
header(‘Content-Type: image/png’);
imagepng($img, ‘render_’ . time() . ‘.png’);

?>

 

Ny problemformulering marts 24, 2009

Arkiveret i: Uncategorized — jesperfriis @ 11:04 am

- Hvordan bruger man Flash og AS3 sammen med PHP og MySQL?

- Hvilke forskellige typer af applikationer kan man med fordel lave, når man bruger disse teknologier sammen?

- Hvordan kan jeg blive bedre til AS3, PHP og mySQL?

- Hvordan bliver jeg bedre og mere erfaren til at arbejde med en webserver og en database?

 

Tegne applikation marts 23, 2009

Arkiveret i: Uncategorized — jesperfriis @ 11:13 am

Ved hjælp af den tegne API der er inkluderet i Flash kan man designe sine egne tegne applikationer. Den kan ses og prøves her:  http://www.jesperf.dk/flashandphp/drawing/index.html

Det er så meningen i de kommende applikationer, jeg skal prøve at lave, at man bl.a. kan gemme det billede, man tegner ved hjælp af noget, der hedder GD Library i PHP.

Her kommer AS3 koden:

// the container reference in which you draw
var penMC:MovieClip;
// the boolian variable used to start and stop drawing
var isDrawing:Boolean = false;
// the variables that holds the default pen color and size
var penTipSize:uint = 1;
var penColor:Number = 0×000000;

// this function is responsible for building the toolbox and initializing the mouse event handlers
function init():void
{

// makes a new instance of the penMC movieclip
penMC = new MovieClip();
// set eventhandler on the mouse down,up and move and call a function when they are used
stage.addEventListener(MouseEvent.MOUSE_DOWN, startDrawing);
stage.addEventListener(MouseEvent.MOUSE_UP, stopDrawing);
stage.addEventListener(MouseEvent.MOUSE_MOVE, drawing);

//add the penMC movieclip to the stage
addChild(penMC);

// Puts event listeners on all the colors and line styles in the toolbox, so the can change color an line style
// – by changing the values of the penColor variable and the penTipSize variable
toolsMC.swatchPurpleMC.addEventListener(MouseEvent.CLICK, function():void
{
penColor = 0x9999CC;
});
toolsMC.swatchBlueMC.addEventListener(MouseEvent.CLICK, function():void
{
penColor = 0x0000FF;
});
toolsMC.swatchRedMC.addEventListener(MouseEvent.CLICK, function():void
{
penColor = 0xFF0000;
});
toolsMC.swatchGreenMC.addEventListener(MouseEvent.CLICK, function():void
{
penColor = 0x00FF00;
});
toolsMC.swatchOrangeMC.addEventListener(MouseEvent.CLICK, function():void
{
penColor = 0×009900;

});
toolsMC.swatchBlackMC.addEventListener(MouseEvent.CLICK, function():void
{
penColor = 0×000000;

});

toolsMC.brushSize1MC.addEventListener(MouseEvent.CLICK, function():void
{

penTipSize = 1;
});
toolsMC.brushSize2MC.addEventListener(MouseEvent.CLICK, function():void
{

penTipSize = 2;
});

toolsMC.brushSize4MC.addEventListener(MouseEvent.CLICK, function():void
{
penTipSize = 4;
});

toolsMC.brushSize6MC.addEventListener(MouseEvent.CLICK, function():void
{
penTipSize = 6;
});

// makes sure you can’t accidently draw on the tool interface, by swapping children
swapChildren(toolsMC, penMC);
}

// the function that enables you to start drawing, and it is called when the mouse is clicked
function startDrawing(e:MouseEvent):void
{

// the output panel tells you that the function is called!
trace(“Start Drawing”);
// the boolian is set to true so it can be used to determin whether to draw or to stop drawing
isDrawing = true;
// a new default line is created in case the color or size variables has changed.
// it is set inside the penMC movieclip
penMC.graphics.lineStyle(penTipSize, penColor, 1.0);
// Moves the current drawing position to where mouse x and y is inside the penMC movieclip
penMC.graphics.moveTo(mouseX, mouseY);
}

// when the drawing flag is set you can start drawing the actual pen stroke(s)
function drawing(e:MouseEvent):void
{

//you can draw if “isDrawing” is set to true
if(isDrawing)
{

// draws a line from the current position of the mouse pointer in the penMC movieclip
penMC.graphics.lineTo(mouseX, mouseY);
}
}

// when the mouse button is released you stop drawing
function stopDrawing(e:MouseEvent):void
{

// you get a message in the output panel when you stop (only in your fla file)
trace(“Stop Drawing”);
// the stop drawing is done by setting the boolian to false
isDrawing = false;
}
// calls the init function
init();

 

flickr gallery marts 20, 2009

Arkiveret i: Uncategorized — jesperfriis @ 11:32 am

Så har jeg også lavet et billede galleri, hvor jeg har brugt den API, som flickr stiller gratis til rådighed. Man søger så efter billeder i en bestemt katagori, og flickr returnerer billeder fra deres database.  Det eneste, man skal gøre, er at oprette en flickr account på http://flickr.com/signup og derefter ansøge om en API på http://flickr.com/services/api/keys/apply

Denne applikation minder meget om den forrige applikation, jeg lavede nemlig “amazon search” applikationen. Koden er også mange steder næsten den samme, og hvis man lavede endnu større applikationer, er det her, at det ville være en stor fordel at lave nogle genbrugelige  AS3 “classes”, som man blot henviser til i sin “package”, og som man så måke bare behøver at ændre små ting i.

Jeg prøvede at kommentere AS3 koden storts set uden brug af bogen, og det var rart, at jeg faktisk selv kunne gennemskue, hvordan koden hang sammen, og hvilken betydning de forskellige variabler, funktioner osv har.

PHP koden kommenterede jeg dog med hjælp fra bogen, da der var flere koder, jeg ikke lige selv kunne gennemskue. Specielt fordi det er noget kode, som kommer fra flickr og er helt nyt for mig.

Galleriet kan ses på http://www.jesperf.dk/flashandphp/flickr_gallery/index.html , men igen så er der problemer med at få lov til at søge og hente billederne  ned, da det har noget med “cross domain policy” at gøre, og det har jeg ikke tid til at undersøge lige nu, hvordan man løser. Et andet problem er, at min server kun understøtter PHP4, og da PHP’en i min kode gør brug af “simpleXML” library, som kun virker i PHP 5, så ville der også komme en fejlmelding, hvis det andet problem var løst. Jeg forstår ikke helt hvorfor, de kun understøtter PHP4, og jeg overvejer at sende dem en mail, hvor jeg spørger hvorfor.

Her kommer koden, og så kan man jo selv prøve det af derhjemme på ens “localhost” server, for der virker det fint , og billedrne fra flickr dukker helt planlagt op, når man søger.

Først AS3 som er i 2 “classes”:

1:
package
{

// imports the nescesary classes
import flash.display.MovieClip;
import flash.events.*;
import flash.net.URLRequest;
import flash.net.URLVariables;
import flash.net.URLLoader;

public class PhotoGallery extends MovieClip
{

// path to the php file on the server
public var webServiceURL:String = “http://localhost/flashandphp/flickrGallery/photoGallery.php”;

// defines the variables to use later, the photos array and the movieclip to hold the photos
private var photos:Array;
private var photosContainer:MovieClip;

// this function runs everytime the search button is clicked (the constructor function)
public function PhotoGallery()
{

//this is only visible in the fla file and this way you can follow the process
trace(“Simple WebService Searcher Started”);
// makes new instance
photos = new Array();
// makes new instance
photosContainer = new MovieClip();
// places the photos movieclip on the stage
photosContainer.y = 75;
// adds an eventlistener to the search button
searchBtn.addEventListener(MouseEvent.CLICK, searchHandler);
//  adds photos movieclip holder to the stage
addChild(photosContainer);
}

// this function is responsible for removing old photos if any
// and to search for photos when something is entered in the “enter keywords” textfield
public function searchHandler(e:MouseEvent):void
{

// it only runs if something is entered
if(searchTxt.text.length > 0)
{

// calls the removeOldPhotos function
removeOldPhotos();

// calls the loadSearchResults function and sends along the keywords entered as an argument
loadSearchResults(searchTxt.text);
}
}

// this function send the request to the php file on the server which connects to flick to search for results
// the php file the sends the requested data back
public function loadSearchResults(tags:String):void
{

//this is only visible in the fla file and this way you can follow the process
trace(“loadSearchResults()”);
var urlVariables:URLVariables = new URLVariables();
urlVariables.tags = tags;

// connects to the php file on the server
var urlRequest:URLRequest = new URLRequest(webServiceURL);
//the dat send to the php file is the tags entered in the “enter keywords” textfield
urlRequest.data = urlVariables;

// uses the loader class to load the data
var urlLoader:URLLoader = new URLLoader();
//when the data is fully loaded the loadedResultsHandler function is called
urlLoader.addEventListener(Event.COMPLETE, loadedResultsHandler);
urlLoader.load(urlRequest);
}

public function loadedResultsHandler(e:Event):void
{
//this is only visible in the fla file and this way you can follow the process
trace(“loadedResultsHandler()”);

// when the data is fully loaded
var urlLoader:URLLoader = URLLoader(e.target);
// its made valid xml data to work with in flash
var xml:XML = new XML(urlLoader.data);

// a for…each loop is used to look through each item in the xml file
for each(var item in xml..photo)
{

// makes a new instance of the photoItem movieclip from the library
var photoItem:PhotoItem = new PhotoItem();
//calls the setValues metod to set title and thumbnail photo
photoItem.setValues(item..title, item..thumb);
// places the photos on top of each other
photoItem.y = (photos.length * (photoItem.height + 50));
// adds the photitem to the photos array
photos.push(photoItem);
// adds photoItem to the photosContainer movieclip on the stage
photosContainer.addChild(photoItem);
}
}

// removes the old photos
private function removeOldPhotos():void
{

// only removes photos if there are any
if(photos.length > 0)
{

// makes new array to clear the old one
photos = new Array();
// removes the photosContainer movieclip
removeChild(photosContainer);
// and makes a new on and places and adds it to the stage
photosContainer = new MovieClip();
photosContainer.y = 75;
addChild(photosContainer);
}
}
}
}

2:
package
{

// imports the nescesary classes
import flash.display.MovieClip;
i
mport flash.text.TextField;
import flash.display.Loader;
import flash.net.URLRequest;

public class PhotoItem extends MovieClip
{

// makes the variables to use later(and gives them the string datatype)
private var title:String;
private var thumb:String;

// the constuctor function is empty – doesent mean anything!
public function photoItem()
{

}

//This function takes the two argument from (photoItem.setValues(item..title, item..thumb)
// and datatypes them to strings
public function setValues(t:String, i:String):void
{

// makes the variables private, so they can’t accidently be changed or modified
title = t;
thumb = i;

// sets the title retrieved from the xml equal to the titleTxt text
titleTxt.text = title;
//places it on the stage in the titleTxt textfield component. And moves it out so there are room for the thumbnail
titleTxt.x = 100;

// calls the loadthumb function
loadThumb();
}

// this function loads the thumbnail images through the url provided from flikr which was sent to php and sent back to flash as xml
public function loadThumb():void
{

//this is only visible in the fla file and this way you can follow the process
trace(“load thumb”);
//loads the thumbnail image
var thumbLoader:Loader = new Loader();
var thumbURL:String = thumb;
var thumbURLRequest:URLRequest = new URLRequest(thumbURL);
thumbLoader.load(thumbURLRequest);
thumbLoader.x = 10;

addChild(thumbLoader);
}

// don’t know what this function does because the application runs perfect without
// but in the book he says: “this method is for passing back the image information”.
public function getValues():Object
{
return {title:title};
}
}
}

Php’en ser således ud:

<?php

// first step is to define the flickr API key that is provided from flickr
define(“FLICKR_ACCESS_KEY”, “flickr API key copy in here!”
);

// flickr har a uniqe way of building image URLs and by later in this php code the use of sprintf function is used to work with that format
$flickrURLTemplate = “http://farm%s.static.flickr.com/%s/%s_%s_s.jpg”;

// if the search tags that comes from flash accidently is empty the php script stops and exits
if(empty($_GET['tags']))
{
exit();
}

// the seach tages from flash is stored in the searchTags variable
$searchTags = $_GET['tags'];

// next step is to pull in the search tags data and make a call to flickr to start the search process
$apiMethod = “flickr.photos.search”;
$request = “http://api.flickr.com/services/rest/?method=” . $apiMethod . “&tags=” . $searchTags  .”&api_key=” . FLICKR_ACCESS_KEY. “&per_page=5″;

// the XML data returned is stores in the rawXml variable
$rawXml = file_get_contents($request);
// when its fully loaded it is passes along to the simplexml_load_string method which creates a proper object tha php can then parse
$xmlResponse = simplexml_load_string($rawXml);

// how many images to display is determined by loading the value that is located in the XML
$nodeCount = getAttribute($xmlResponse->photos, “perpage”);

// the process of building the custom XML document is done using a for.. each loop that graps each photo node and pulls in the required information
$xml = “<?xml version=\”1.0\” ?>\n<photos>”;

for($i=0; $i < $nodeCount; $i++)
{
// Flickr vars
// this is for building the image path, which is pased into the sprintf function
$farmID = getAttribute($xmlResponse->photos->photo[$i], “farm”);
$serverID = getAttribute($xmlResponse->photos->photo[$i], “server”);
$photoID = getAttribute($xmlResponse->photos->photo[$i], “id”);
$secret = getAttribute($xmlResponse->photos->photo[$i], “secret”);

$xml .= “    <photo>”;
$xml .= “        <title><![CDATA[" . getAttribute($xmlResponse->photos->photo[$i], “title”) . “]]></title>”;
$xml .= “        <thumb>” . sprintf($flickrURLTemplate, $farmID, $serverID, $photoID, $secret) . “</thumb>”;
$xml .= “    </photo>”;

}

$xml .= “</photos>”;

// sets the correct header type
header(“content-type: text/xml”);

// the data sent back to flash in an XML document
print $xml;

// the    getAttribute function with two arguments taht helps build the right xml document.
function getAttribute($xml, $name)
{
foreach($xml->attributes() as $key=>$val)

{
if($key == $name)
{
return (string)$val;
}
}

// returns false if this comparison isnt true: ($key == $name)
return false;
}

?>

 

Amazon search marts 19, 2009

Arkiveret i: Uncategorized — jesperfriis @ 1:27 pm

Så har jeg færdiggjort en applikation, der ved hjælp af Amazon.com’s AWS (Amazon Web Service) gør det muligt at lave en søge applikation, der bruger Amazon.com som data kilde. Dvs at man gør brug af ECS (Amazon E-Commerce Service), som giver direkte adgang til Amazons fantastiske søgesystem. Det eneste man skal gøre er, at anskaffe sig en valid Amazon access ID, som man får, når man opretter en”developer’s account” på www.amazon.com/gp/aws/landing.html. Det er nemt, hurtigt og koster ikke noget. Man skal bare have en email adresse.

Når man så søger, får man rigtigt meget xml data tilbage fra Amazon, og så er det vigtigt, at man får sorteret i det i sin php fil, så man kun får det data ud, som man skal bruge og derefter kan sende det videre til swf filen og flash.

Min applikation virkede fint på min localhost server, men da jeg uploadede den til min server på nette,t kunne den ikke skabe forbindelse. Jeg tror endnu engang, det har noget med cross domain policy at gøre, da jeg henter data fra en anden web server, som så skal igennem den server, hvor mit domain er. Derfor virker applikationen ikke, men man kan se, hvordan den ser ud her: http://www.jesperf.dk/flashandphp/amazon_search/index.html

Og hvis man så kunne søge og søgte på flash, så ville der komme 4 eksempler frem med et lille billede a bogen og en tittel samt forfatterens navn.

Jeg synes, det er super at finde ud af de mange muligheder, man har for at lave forskellige applikationer ved hjælp af forskellige servicer, der bliver stillet gratis til rådighed fra andre web firmaer. Det var en god oplevelse at sidde og søge efter forskellige bøger (igennem min localhost), og de så rent faktisk dukkede op i min swf.

Endnu engang fandt jeg en lille fejl i PHP source filen, men denne gang tog det mig ikke så lang tid at finde den. Det er godt, at jeg kan mærke jeg bliver bedre til de forskellige koder, så jeg kan finde en fejl og komme videre i processen. Det siger vel også lidt om, at jeg da heldigvis lærer noget.

Nå men her kommer koden. Først as3 som er 2 filer eller 2 classes:

1:
package
{

// import the nescesarry classes
import flash.display.MovieClip;
import flash.events.*;
import flash.net.URLRequest;
import flash.net.URLVariables;
import flash.net.URLLoader;

// extends on existing movieclips from the library
public class BookSearch extends MovieClip
{

// path to the php file on the server
public var webServiceURL:String = “http://jesperf.dk/flashandphp/amazon_search/bookSearch.php”;

//creates an array variable
private var bookItems:Array;
////creates movieclip variable
private var bookItemsContainer:MovieClip;

// the constructor method tah runs each time the application starts
// it is used to initialize the array, create a container movieclip and add en event listener to the search button
public function BookSearch()
{
bookItems = new Array();
bookItemsContainer = new MovieClip();

// the movieclip to hold the book items is placed
bookItemsContainer.y = 100;
// the search button calls teh serarchHandler function
searchBtn.addEventListener(MouseEvent.CLICK, searchHandler);
// – and added to the stage
addChild(bookItemsContainer);
}

// this functiom handles the seach request
public function searchHandler(e:MouseEvent):void
{

// if something is entered in the search textfiels then old seach results are removed, otherwise they stay
if(searchTxt.text.length > 0)
{

// calls the removeOldResults function
removeOldResults();
// and if somthing is entered a call to the loadSearchResults function is made to connect to php and search for the result
loadSearchResults(searchTxt.text);
}
}

// this function send a request to the php file which is responsible for interfacing with the AWS
// and it takes one argument that is the string entered in the search button texfield
public function loadSearchResults(terms:String):void
{

// first set up the variables object
var urlVariables:URLVariables = new URLVariables();
urlVariables.terms = terms;

// calls the php and assigns that to the URLRequest
var urlRequest:URLRequest = new URLRequest(webServiceURL);
urlRequest.data = urlVariables;

// Creates a new loader instance
var urlLoader:URLLoader = new URLLoader();
// assigns an event handler
urlLoader.addEventListener(Event.COMPLETE, loadedResultsHandler);
urlLoader.load(urlRequest);
}

// Once the Web server returns the data, it is sent to the loadedResultsHandler method
// the responce is sent in XML format and using a for … each loop each element is pulled out and sent to a unique bookItem instance
public function loadedResultsHandler(e:Event):void
{
var urlLoader:URLLoader = URLLoader(e.target);
var xml:XML = new XML(urlLoader.data);

for each(var item in xml..book)
{
// a new instance of the bookitem from the library is made
var bookItem:BookItem = new BookItem();
// the new instance gets its unique values
bookItem.setValues(item..title, item..author, item..price, item..thumb);
// with a little help from the array the item are positioned on top of each other
bookItem.y = (bookItems.length * (bookItem.height + 30));
// the book items are added to the booItems array
bookItems.push(bookItem);
// the bookItem movieclip is placed inside the bookItemsContainer movieclip
bookItemsContainer.addChild(bookItem);
}
}

// this method is used to remove the existing book item instances
// this metod is called each time a new search begins, to ensure the data dosent accidentially stack up
private function removeOldResults():void
{

/// checks for valid entries because the first time the application runs there will be no existing products on the stage
if(bookItems.length > 0)
{

// a new array is created that clears the existing objects
bookItems = new Array();
// then the old container is cleared and a new is created
removeChild(bookItemsContainer);
bookItemsContainer = new MovieClip();
bookItemsContainer.y = 100;

// adding the new instance of the container to the stage
addChild(bookItemsContainer);
}
}
}
}

2:
package
{

// imports the nescesarry classes
import flash.display.MovieClip;
import flash.text.TextField;
import flash.display.Loader;
import flash.net.URLRequest;

// this class is used for each product that is added to the stage. It is responsible for storing off the product data and loading the book thumbnail
// it also extends on existing movieclips from the library
public class BookItem extends MovieClip
{

// creates the variables to use in the setValues function
private var title:String;
private var author:String;
private var price:String;
private var thumb:String;

// The constuctor method is empty in this class!
public function BookItem()
{

}

// this function is responsible for storing the passed values or book data retrieved from Amazon
public function setValues(t:String, a:String, p:String, i:String):void
{
title = t;
author = a;
price = p;
thumb = i;

titleTxt.text = title;
authorTxt.text = author;
priceTxt.text = price;

// a call to the loadThumb function is made which is responsible for retrieving the thumbnail of the book cover
loadThumb();
}

// loads the thumbnail of the book cover through the url passes back to php in the XML from Amazone
public function loadThumb():void
{
var thumbLoader:Loader = new Loader();

var thumbURL:String = thumb;
var thumbURLRequest:URLRequest = new URLRequest(thumbURL);
thumbLoader.load(thumbURLRequest);
thumbLoader.x = 10;

// when using the loader class you can pass it into the addChild which removes the need for an event listener (because you don’t need the big cover)
addChild(thumbLoader);
}

// the last method is for returning the BookItem data that was populated in the previous methods
// don’t quite know whats it there fore because the application runs without this function,
// – but maybe its so that you can use the variables without using the setValues function
public function getValues():Object
{
return {title:title, author:author, price:price};
}
}
}

PHP’en:

<?php

// the variable to hold the seach requests
$terms = “”;

//
define(“AWS_ACCESS_KEY”, “AWS_ACCESS_KEY“);

// checks to see if the search field is empty (or checks for valid tags)
if(!empty($_GET['terms']))
{

// the variable to holdt the search parameters sent with get method
$terms = $_GET['terms'];

// the request that will be sent to the AWS passing along the search parameters
$request = ‘http://ecs.amazonaws.com/onca/xml’ .
‘?Service=AWSECommerceService&’ .
‘AWSAccessKeyId=’ . AWS_ACCESS_KEY .
‘&Operation=ItemSearch’ .
‘&SearchIndex=Books’ .
‘&ResponseGroup=Medium’ .
‘&Keywords=’ . $terms;

// the response from the AWS is loaded using file_get_contents
// the string is saved to the $rawXml

$rawXml = file_get_contents($request);

// a call to the simplexml library i made to build a properly formatted xml object
$xmlResponse = simplexml_load_string($rawXml);

// the variable to hold the 4 xml nodes (only 4 book results are saved)
$nodeCount = 4;

// the XML sent back to flash
// seaches for 4 books through the for loop and gets the title, author, price and thumb by going througt items and items nodes an so on…
$xml = “<?xml version=\”1.0\” ?>\n<books>”;

for($i=0; $i < $nodeCount; $i++)
{
$xml .= “    <book>”;
$xml .= “        <title><![CDATA[" . $xmlResponse->Items->Item[$i]->ItemAttributes->Title . “]]></title>”;
$xml .= “        <author><![CDATA[" . $xmlResponse->Items->Item[$i]->ItemAttributes->Author . “]]></author>”;
$xml .= “        <price><![CDATA[" . $xmlResponse->Items->Item[$i]->ItemAttributes->ListPrice->FormattedPrice . “]]></price>”;

$xml .= “        <thumb>” . $xmlResponse->Items->Item[$i]->SmallImage->URL . “</thumb>”;
$xml .= “    </book>”;
}

$xml .= “</books>”;

// creates the right header type so XML readers know the format that is being sent
header(“content-type: text/xml”);

// outputs the xml tahts sent to flash
print $xml;

}

?>

 

Lidt PHP update marts 17, 2009

Arkiveret i: Uncategorized — jesperfriis @ 2:01 pm

Jeg har de to sidste dage haft behov for at få lidt bedre styr på noget PHP, og jeg har derfor haft gang i en rigtig god tutorial fra Linda.com som hedder PHP & MySQl Essential Training, samt at jeg også har læst et par kapitler i “Learning PHP” fra O’REILLY. Det var primært noget med arrays, funktioner og xml jeg ville have bedre styr på.

Jeg vil også gerne have bedre styr på “classes” i PHP, men det må jeg se på lidt senere, da der ikke er så meget om dette, hverken i tutorialen eller i bogen, og samtidig har også behov for at komme videre i processen lige nu.

 

Shoppingcart afslutning!!! marts 17, 2009

Arkiveret i: Uncategorized — jesperfriis @ 1:51 pm

Så lykkedes det mig endelig at finde fejlen.

Jeg fik en ny mail tilbage fra forfatteren, og den lød sådan her:

Did you merge the code from the two projects or simply run the code from the link I provided? I think something happened with the code for the book, but the link I provided before does work. As long as my site is online.
Hope that helps,
Matt
Dette fik mig til at tænke, at der nok var et eller andet galt med kommunikationen mellem koden i fla filen ( the timeline code) og de tre classes. Så det eneste jeg skulle gøre, var selvfølgelig bare at flytte de tre AS filer ind i samme mappe som fla filen. En lidt åndsvag fejl at bruge så meget tid på, men man tror jo at tingene er i den orden, som de skal være, når man downloader nogle source files til en bog. Det viste sig dog også, at der var en lille fejl i koden, men det var ikke i den kode, der var beskrevet i bogen, men kun den i de souce files, jeg havde downloaded, og den var til at regne ud, hvis han ikke havde givet mig linket til den nye source kode.
Her er hvad, jeg så skrev tilbage til ham:

Hi again
Finally I managed to make it work.

I just had to put the AS files in the same directory as the Fla file! I guess I should have figured it out myself a bit earlier.
There is one error in the code in the source files I downloaded in the first place. It is in the line:
item.setStoreData(id, xmlItem.attribute(‘name’), xmlItem.attribute(‘desc’), xmlItem.attribute(‘thumbnail’), xmlItem.attribute(‘price’));
where the last argument (xmlItem.attribute(‘price’) ) was missing,  but I can see its not missing in the source code provided in the book, so I guess i could have figured that out to.
Thanks for the help once again
Jesper
Eksemplet kan ses her: http://jesperf.dk/flashandphp/shopping_cart/index.html
Man skal være opmærksom på at hvis man trykker på “checkout” knappen så får man en fejlmelding. Dette er fordi PHP koden benytter sig af “SimpleXMLElement”, som ikke er understøttet af PHP 4, som min webserver desværre kun har.
Koden til denne applikation består af tre seperate classes plus en i fla.filen. Samtidig er der to PHP filer, og så er der jo også databasen, som man skal oprette med noget indhold. Jeg har derfor valgt ikke at poste denne kode, selvom jeg har kommenteret den, da jeg synes det vil komme til at fylde for meget og virke uoverskueligt.
 

 
Follow

Get every new post delivered to your Inbox.