How add UNDO to my text field in AS3? - actionscript-3

I have a simple text editor with cut, paste and undo buttons. I have this for cut and paste but i don't how to create undo button?
var clipboardFmt:TextFormat = new TextFormat();
var initialPoint:Number = new Number();
var finalpoint:Number = new Number();
var clipBoard:String = new String();
cut_button.addEventListener(MouseEvent.CLICK,cutText);
paste_button.addEventListener(MouseEvent.CLICK, pastefromClipboard);
function cutText(event:MouseEvent):void
{
clipBoard = txt.text.substring(txt.selectionBeginIndex,txt.selectionEndIndex);
System.setClipboard(clipBoard);
txt.replaceText(txt.selectionBeginIndex,txt.selectionEndIndex,"");
}
function pastefromClipboard(e:Event):void
{
txt.replaceText(txt.selectionBeginIndex,txt.selectionEndIndex,clipBoard);
finalpoint = initialPoint + clipBoard.length;
txt.setSelection(initialPoint,finalpoint);
txt.setTextFormat(clipboardFmt, initialPoint,finalpoint);
}
txt.addEventListener(Event.CHANGE,count);
function count(e:Event):void
{
wn.text = countWords(txt.text);
function countWords(input:String):int
{
return input.match(/[^\s]+/g).length;
}
}

You need to store a copy of text-field text in a variable. Each time text-field's value is being changed but before the change is applied (the event is called TextEvent.TEXT_INPUT) save a copy of text-field value into this variable. When undo button is pressed set text-field value to a value stored in this variable.
This is the simplest solution which will allow you to undo only one step back. You can use an array instead of single variable in order to store several states of text-field which will allow you to undo several steps back.

create an array based undo system. Don't use the clipboard it will not work.

Related

How to remove child with same name if in same location or collision? AS3

So, in my script I have given the user the ability to make unlimited amount of a certain movieclip.
var square = new Square();
sqaure.x = mouseX;
sqaure.y = mouseY;
addChild(square);
However, I would like to have the script remove any extra children added to the same X and Y coordinates. I need to make sure it removes the extra child even if they click and move the cursor away and then click back to an already populated location later. Either in the .class file or in the main script itself.
Any ideas? Thanks
At the moment of click you can obtain a list of all the things under the mouse cursor with the getObjectsUnderPoint(...) method and remove any subset of them upon criteria of your liking.
// Stage, because if user clicks the current container
// into the empty area, the click won't register.
stage.addEventListener(MouseEvent.MOUSE_DOWN, onDown);
function onDown(e:MouseEvent):void
{
var aPoint:Point = new Point;
// Set it to the mouse coordinates.
aPoint.x = mouseX;
aPoint.y = mouseY;
// Convert it to Stage coordinates.
aPoint = localToGlobal(aPoint);
// The returned list will contain only descendants
// of the current DisplayObjectContainer.
var aList:Array = getObjectsUnderPoint(aPoint);
// Iterate through the results.
for each (var aChild:DiaplayObject in aList)
{
// Now, filter the results to match certain criteria.
// Don't bother with the grandchildren.
if (aChild.parent != this) continue;
// Ignore things if they are not of the right class.
if (!(aChild is Square)) continue;
// ...etc.
// Remove those ones that have passed all the checks.
removeChild(aChild);
}
// Add the new one here.
var aSq:Square = new Square;
aSq.x = mouseX;
aSq.y = mouseY;
addChild(aSq);
}
One thing that Organis said, the "addEventListener" is something you can take a look at using the search terms "as3 event listener api". the "api" searches will come up with adobe specific code and property examples.
You can try to put in small input text boxes and a button with an event listener to set x and y to the values of the input text boxes
Another thing, I've always done it best with arrays to hold every item that you are adding to the stage.
//global variables
var nameSprite:Sprite;
var name2Array:Array = new Array();
var id:Number = 0;
//initial function
nameSprite = new Sprite();
addChild(nameSprite);
name2Array = new Array();//seems redundant but has been what I've had to do to make it work
//other function to add items to the array
var sqaure:objectName = new objectName();
sqaure.x = mouseX;
sqaure.y = mouseY;
square.id = id;//I like to add an id to be able to better sort things
nameSprite.addChild(sqaure);
name2Array.push(sqaure);
id++;
//function to remove items
IndexPH = j;//j would be the index in the for loop to identify the entry to be removed
nameSprite.removeChild(name2Array[IndexPH]);//removes from stage
name2Array.splice(IndexPH,1);//removes from array
//function to sort the array after an item has been removed
name2Array.sortOn(["id"], Array.NUMERIC);
So this is a bunch of things that you can mess around with if you need ideas. I tend to search and search and then find a little bit of code to incorporate into my projects while not necessarily using every part of a specific code example.

How can I save variables to a file? Actionscript 3.0

I'm not really very good with Actionscript 3.0 and I was wondering how I can save variables to a file (A .txt), as well as set variables using a button.
What I am trying to do is get a name, date and another name. I have 3 input boxes and I am unsure how to get the text input to be saved into a text file. I need it to create a new file every time it saves so the details of each user is saved (This is my task, it's an induction thingy, nothing bad).
Also, I am unsure how to set variables with the click of a button. Say the button instance name is "next_button" and I want to get it to set a variable that I can call later on. If I click it, the variable will be set to "Contractor", that's what I need.
The start of the "quiz" if you would call it is asking for the name, date and the company they're from. I need those details to be saved to a file.
I also need help with getting a variable to be set with the click of a button. I have 4 buttons on the screen and I want to get the button to change a variable to "Permanent Employee" or "Contractor".
Any help is appreciated.
To save data using the FileReference Class:
var data:String = "JDLKJFSDKJFHS";
var file:FileReference = new FileReference();
file.save(data,"filepath.txt");
To set a variable on mouse click:
var saveVar:String = "";
var buttons:Array = [button1,button2,button3];
var buttonStrings:Array = ["Contractor","Employee","Slave"];
button.addEventListener(MouseEvent.CLICK,onClick);
function onClick(e:MouseEvent):void{
var index:int = buttons.indexOf(e.target);
if (index > 0) saveVar = buttonStrings[index];
}

Removing an EventListener from an object decided via an Array

I am making a simple calculator for an assignment in my IT-Class. It has 3 textboxes where the user can add his numbers, and the boxes start with a "0" inside of them, to show that the user is supposed to write numbers here. What I wanna do, is have this zero go away as the user puts focus on the box.
Since I have 3 boxes, I wanted to make the EventListener call up a function that removes the text and the Eventlistener, instead of writing the same code 3 times.
Using an array containing the different textboxes I managed to call them up, and change the text as I wanted, but the EventListener isn't being removed, so the text the user writes in is being removed when they focus on the textbox again
///////////////////////////////////////////////////////////////////////////////////
//The Array containing all the TextFields
var textFieldArr:Array = new Array(txtNumber1,txtNumber2,txtNumber2)
function onFocus(i:int){
return function (evt:FocusEvent){
textFieldArr[i].text = "";
textFieldArr[i].removeEventListener(FocusEvent.FOCUS_IN, onFocus(i))
}
}
//Calls up the onFocus function and declares variable i
txtNumber1.addEventListener(FocusEvent.FOCUS_IN, onFocus(0));
txtNumber2.addEventListener(FocusEvent.FOCUS_IN, onFocus(1));
txtNumber3.addEventListener(FocusEvent.FOCUS_IN, onFocus(2));
///////////////////////////////////////////////////////////////////////////////
Your event listener isn't being removed, because when you call onFocus(i) within the removeEventListener param, you are being returned a new function, and not the function that was originally being triggered by the event. The other problem with your code is that 'i' does not exist in the listener function you have declared -- you need to use only the properties of evt to figure out which text field to target, and the correct event listener to remove.
The common/correct way to do this is to use a event-accepting function, and listen to each text field with it. You don't even need the array anymore unless you have some other use for it.
function onFocusIn(evt:FocusEvent):void{
trace("onFocusIn("+evt.target+")");
var focusedField:TextField = TextField(evt.target);
if(focusedField){
focusedField.text = "";
focusedField.removeEventListener(FocusEvent.FOCUS_IN, onFocusIn);
}
}
txtNumber1.addEventListener(FocusEvent.FOCUS_IN, onFocusIn);
txtNumber2.addEventListener(FocusEvent.FOCUS_IN, onFocusIn);
txtNumber3.addEventListener(FocusEvent.FOCUS_IN, onFocusIn);
Listener is not removed, because onFocus returns on each invocation new Function instance.
You might try use target property of FocusEvent class:
var textFieldArr:Array = new Array(txtNumber1,txtNumber2,txtNumber2)
function onFocus(evt:FocusEvent){
TextField(evt.target).text = "";
TextField(evt.target).removeEventListener(FocusEvent.FOCUS_IN, onFocus)
}
//Calls up the onFocus function and declares variable i
txtNumber1.addEventListener(FocusEvent.FOCUS_IN, onFocus);
txtNumber2.addEventListener(FocusEvent.FOCUS_IN, onFocus);
txtNumber3.addEventListener(FocusEvent.FOCUS_IN, onFocus);

Recognize previous random number

i write a few lines codes that when i click on the button, a random number will be generated.
then a random child will be show up on the stage.
but i'm trying to when i click again on the button, the previous child has been removed and new child with new random number will be replaced.
how can i do that?
or how can i find out what's the previous random number?
function clkBtn(evt:MouseEvent):void
{
i=(Math.floor(Math.random()*10));
addChild(picP[i]);
removeChild(picP[?]);
}
Just save a reference to the DisplayObject you are adding to the stage and then remove it on the next time the click function is called.
var displayObject:DisplayObject = null;
function clkBtn(evt:MouseEvent):void {
if(displayObject)
removeChild(displayObject);
var i:int = Math.floor(Math.random()*10);
displayObject = picP[i];
addChild(displayObject);
}

Saving textfield input

I'll explain a little before asking my question ... I've created numerous games which load and unload off a main menu.
The player enters their name on the main menu before playing any games and when the player completes a game I want to save their time (taken to complete the game) and unload this time back into the main menu.
Is there any way of saving the times using AS3 to a word document or something like this? I can't send the times to my website with php because the games will be used within a competition and it all needs to work with the internet.
Any ideas guys?
Edit:
var dataloader:URLLoader = new URLLoader();
var dataarray:Array = new Array(); // do this where you intialise other vars
function preparesave()
{
dataloader.load(new URLRequest("savedata.txt"));
}
dataloader.addEventListener(Event.COMPLETE,savedata);
function savedata (event:Event)
{
dataarray = event.target.data.split(/\n/);
dataarray.push(MyTimer);
var bytes:ByteArray = new ByteArray();
var fileRef:FileReference = new FileReference();
for (var i = 0; i < dataarray.length;i++)
{
bytes.writeMultiByte(dataarray[i] + "\n", "iso-8859-1");
bytes.writeMultiByte('English Game Time: ',"iso-8859-1");
bytes.writeMultiByte(HourText.text.toString(),"iso-8859-1");
bytes.writeMultiByte(':',"iso-8859-1");
bytes.writeMultiByte(MinuteText.text.toString(),"iso-8859-1");
bytes.writeMultiByte(':',"iso-8859-1");
bytes.writeMultiByte(SecondText.text.toString(),"iso-8859-1");
}
fileRef.save(bytes,"savedata.txt")
}
You could use a cookie(sharedObject) for this purpuse. See http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/SharedObject.html
var data:SharedObject = SharedObject.getLocal("userdata");
data.startTime = new Date().time;
If you need the startTime again you could just retrieve it by the cookie and variable name.
For small amounts of data, you're best-off just going with automaticoo's solution by using SharedObjects.. they take minimal time to set up and are an efficient way of storing small amounts of data.
However, if it's not for you, you could always load/save to a text file. You can do this using ByteArrays and FileReferences.
Since you brought up saving to a word file, I would suggest saving to a text file would be the best way of achieving your goal (although other than your word doc. suggestion, i'm not sure.. your aim is sort of unclear)
Here is a seriously quick demonstration of saving to a text file.. If you need help loading it too, let me know.
function savedata() {
var bytes:ByteArray = new ByteArray();
var fileRef:FileReference = new FileReference();
bytes.writeMultiByte(playername + "\n", "iso-8859-1");
bytes.writeMultiByte(playerscore.toString(),"iso-8859-1");
fileRef.save(bytes,"savedata.txt");
}
This is pretty simply.. By using writeMultiByte, we can write as much data as needed before saving our text file! This is especially useful if you have arrays of data you need to save.
Anyway, the "iso-8859-1" is simply a reference to the character set / file-format being used.. I'm not sure if you can simply write utf-16 etc. instead.. I've always just used it as it is written above.
The result in the text file here will be the following:
Peter
9547 (but up one line)
To load, you can just split data by line, resulting in an array full of strings and ints/numbers (however your scores may work). Again, let me know if you need help doing that.
I'm not sure if this is the most efficient method of achieving what you're after since your goal isn't entirely clear to me, but it has been a very useful way for myself in storing large amounts of data, which I'm guessing you are wanting to do if you are compounding all the scores of players.
edit:
Okay, to the questions you posed below:
To save more than one user's score is simple. Simply have a single array which loads the data from the text file (if the text file exists), then adds the new score to the end of the array, then saves back to the text file.
Here is an example:
var dataloader:URLLoader = new URLLoader();
var dataarray:Array = new Array(); // do this where you intialise other vars
function preparesave() {
dataloader.load(new URLRequest("savedata.txt"));
}
dataloader.addEventListener(Event.COMPLETE,savedata);
function savedata (event:Event) {
dataarray = event.target.data.split(/\n/);
dataarray.push(playername);
dataarray.push(playerscore);
var bytes:ByteArray = new ByteArray();
var fileRef:FileReference = new FileReference();
for (var i = 0; i < dataarray.length;i++) {
bytes.writeMultiByte(dataarray[i] + "\n", "iso-8859-1");
}
fileRef.save(bytes,"savedata.txt")
}
What this does is take any existing save data, pushes it to an array (where one line on your save file is one array data entry), adds your appropriate data, and pushes it back out to the save file.
(2) To load this in whilst in the main menu, simply place this code in the frame of the main menu..
dataloader.load(new URLRequest("savedata.txt"));
dataloader.addEventListener(Event.COMPLETE,loaddata);
function loaddata (event:Event) {
dataarray = event.target.data.split(/\n/);
}
This will load all your existing data into an array. What you do from then on is up to you.