Removing TextFields in a loop - actionscript-2

I am trying to create and later remove some Textfields from my stage.
for(i=0;i<Chars.length;i++){
temp = Chars[i] + "_Label";
_root.createTextField(temp, _root.getNextHighestDepth(), 40, 80+(i*30), 200, 20);
this[temp].html = true;
this[temp].vScrollPolicy = false;
this[temp].selectable = false;
this[temp].styleSheet=Stat_style;
this[temp].htmlText = "<h4>" + eval(Mares[i] + ".Name") + "</h4>";
temp = Chars[i] + "_Health";
_root.createTextField(temp, _root.getNextHighestDepth(), 250, 80+(i*30), 200, 20);
this[temp].html = true;
this[temp].vScrollPolicy = false;
this[temp].selectable = false;
this[temp].styleSheet=Stat_style;
this[temp].htmlText = "<h4>" + eval(Mares[i] + ".Health") + "</h4>";
}
stop();
CTRL_Back.onRelease = function() {
for(i=0;i<Chars.length;i++){
temp = Chars[i] + "_Label";
this[temp].removeTextField();
temp = Chars[i] + "_Health";
this[temp].removeTextField();
}
}
The Creating-Part works just fine. But i cant remove them. When I try it out manually by Char1_Label.removeTextField(); it works but i dont understand why it won't work within my loop.

The problem moment is using of this inside function definition. In this case it refers to your CTRL_Back object not for scope your code written on. So you need to use another reference to your scope. In your case it would be this._parent so your remove line should be like this this._parent[temp].removeTextField();

Related

Moving subforms in standard PDF

I am trying to move subforms in a standard pdf file (not a dynamic XML). I have an old copy of LiveCycle (ES2) and have produced the following code
xfa.host.setFocus(clearArrows);
var gridX = xfa.layout.x(gridPICK);
var gridY = xfa.layout.y(gridPICK);
var gridW = xfa.layout.w(gridPICK);
var gridH = xfa.layout.h(gridPICK);
var markerDim = 0;
var mouseX = event.target.mouseX;
var newX = (mouseX + "points").toString();
var mouseY = xfa.layout.h(Page3) - event.target.mouseY;
var newY = (mouseY + "points").toString();
for (var i = 0; i < 10; i++){
var indicatorObject = xfa.resolveNode("Indicator[" + i.toString() + "]");
var indicatorX = xfa.layout.x(indicatorObject);
if (indicatorX < gridX) {
var pointIndicator = indicatorObject;
pointIndicator.presence = "visible";
xfa.host.setFocus(pointIndicator.Description);
xfa.host.openList("Indicator[" + i.toString() + "].Description");
i = 10;
}
}
if (mouseX <= gridX + markerDim)
{
pointIndicator.x = (gridX + markerDim + "points").toString();
}
else if (mouseX >= gridX + gridW - markerDim)
{
pointIndicator.x = (gridX + gridW - markerDim + "points").toString();
}
else
{
pointIndicator.x = newX;
}
if (mouseY >= gridY + gridH - markerDim)
{
pointIndicator.y = (gridY + gridH - markerDim + "points").toString();
}
else if (mouseY <= gridY + markerDim)
{
pointIndicator.y = (gridY + markerDim + "points").toString();
}
else
{
pointIndicator.y = newY;
}
This works fine if I extend the features and use it on a PC or mac however if I try to use it on an ipad it does not work. Essentially this code is placed on the click event of a large button in a grid square.
Any help would be greatly appreciated.
I'm afraid I don't think you'll be able to get this to work.
The iPad version of Adobe Reader does not support XFA forms designed in LiveCycle Designer.

remove ticker for individual object in createjs

I want to remove the listener for individual objects that are animating. I want to remove the ticker for individual objects because they will stop at different times when they reach 200px in y. This code is one frame in Adobe Animate. So this code is not working:
this.stop();
that= this;
var aParticle;
var mySpeed = 12;
var myRotation = 4;
var totalParticles = 5;
var stopParticles = false;
var particleHolder = new createjs.Container();
var count = 0;
var collission_ar = [this.parent.mc_coll0, this.parent.mc_coll1, `this.parent.mc_coll2, this.parent.mc_coll3, this.parent.mc_coll4, this.parent.mc_coll5, this.parent.mc_coll6, this.parent.mc_coll7, this.parent.mc_coll8, this.parent.mc_coll9, this.parent.mc_coll10, this.parent.mc_coll11, this.parent.mc_coll12, this.parent.mc_coll13, this.parent.mc_coll14];`
var totalCollisions = collission_ar.length;
this.addChild(particleHolder);
//stage.update();
var xRange = width;
var yRange = height;
var scaleNum = 1;
//var collisionMethod = ndgmr.checkPixelCollision;
this.scaleX = 1;
this.scaleY = 1;
createParticles()
setTimeout(function(){
removeTimer();
}, 5000)
function createParticles(){
var particle_ar = [];
var randNum = Math.ceil(Math.random() * totalParticles);
aParticle = new lib['MC_leaf'+randNum]();
aParticle.name = 'MC_leaf'+count;
aParticle.x = Math.random() * xRange;
aParticle.y = -Math.random() * 15;
theNum = Math.random() * scaleNum;
aParticle.scaleX = theNum
aParticle.scaleY = theNum
aParticle.alpha = 1;
aParticle.collision = Math.floor(Math.random() * 2);
particleHolder.addChild(aParticle);
aParticle.addEventListener("tick", animateParticle.bind(that));
if(!stopParticles){
timer = setTimeout(function() { createParticles() }, 100);
}
count++;
}
function animateParticle (event){
var part = event.currentTarget;
event.currentTarget.y += mySpeed
event.currentTarget.x += Math.random()/10
event.currentTarget.rotation += myRotation;
if (part.y > 200) {
if(part.name == 'MC_leaf0') console.log('part0 y '+part.y);
part.removeEventListener("tick", animateParticle.bind(that));
}
}
function removeTimer() {
stopParticles = true;
timer = clearInterval();
}
var timer = setTimeout(function() { createParticles() }, 100, that);
So this code is just ignored:
part.removeEventListener("tick", animateParticle.bind(that));
You must pass a reference to the same method in removeEventListener that you used with addEventListener. When you use bind, it generates a wrapper function each time.
// This won't work.
part.removeEventListener("tick", animateParticle.bind(that));
A simple workaround is to store a reference to the bound function, and use that.
aParticle.tickHandler = animateParticle.bind(that);
aParticle.addEventListener("tick", aParticle.tickHandler);
Then use it when removing the listener
part.removeEventListener("tick", part.tickHandler);
There is a better way to handle this though. If you use the utility on() method instead of addEventListener, you can easily remove the method inside the handler.
aParticle.on("tick", animateParticle, that);
// Then when removing:
function animateParticle(event) {
if (conditions) {
event.remove();
}
}
The on() method also has a scope parameter, so you can skip the function binding. It is important to note though that the on() method does its own internal binding, so to remove a listener the usual way, you have to store a reference to it as well.
var listener = target.on("tick", handler, this);
listener.off("tick", listener);
Hope that helps!

Trying to create multiple PDF for each row in a Google Sheet

I am trying to create a separate PDF for each row in a Google Sheet using a Google Doc as a template. I can get it to work when I use the active row; however, when I try to loop the createpdf function the only PDF I am left with is the last row. My thoughts are that I am deleting all of the files beforehand but I can't figure out where the error is. Any help would be awesome.
var TEMPLATE_ID = '1Mxrm0kny8R7ROlBou8kSUc8dOvvH8PvtQ-EC_Nd3FUQ';
function onOpen() {
SpreadsheetApp
.getUi()
.createMenu('Create PDF')
.addItem('Create PDF', 'createPdf')
.addToUi();
}
for (var i=2; i < 3; i++) { function createPdf() {
if (TEMPLATE_ID === '') {
SpreadsheetApp.getUi().alert('TEMPLATE_ID needs to be defined in code.gs');
return;
}
// Set up the docs and the spreadsheet access
var copyFile = DriveApp.getFileById(TEMPLATE_ID).makeCopy(),
copyId = copyFile.getId(),
copyDoc = DocumentApp.openById(copyId),
copyBody = copyDoc.getBody(),
activeSheet = SpreadsheetApp.getActiveSheet(),
numberOfColumns = activeSheet.getLastColumn(),
activeRow = activeSheet.getRange(i, 1, 1, numberOfColumns).getValues(),
headerRow = activeSheet.getRange(1, 1, 1, numberOfColumns).getValues(),
columnIndex = 0,
fileName = activeRow[0][0] + activeRow[0][1],
pdfFile,
pdfFile2;
// Replace the keys with the spreadsheet values
for (;columnIndex < headerRow[0].length; columnIndex++) {
copyBody.replaceText('%' + headerRow[0][columnIndex] + '%',
activeRow[0][columnIndex]);
}
// Create the PDF file and delete the doc copy
copyDoc.saveAndClose();
pdfFile = DriveApp.createFile(copyFile.getAs("application/pdf"));
pdfFile2 = pdfFile.setName(fileName)
copyFile.setTrashed(true);
return pdfFile2;
}}
Tip: pay attention to formatting your code properly, because it will help you understand its structure. Here's what you have after passing it through jsbeautifier:
var TEMPLATE_ID = '1Mxrm0kny8R7ROlBou8kSUc8dOvvH8PvtQ-EC_Nd3FUQ';
function onOpen() {
SpreadsheetApp
.getUi()
.createMenu('Create PDF')
.addItem('Create PDF', 'createPdf')
.addToUi();
}
for (var i = 2; i < 3; i++) {
function createPdf() {
if (TEMPLATE_ID === '') {
SpreadsheetApp.getUi().alert('TEMPLATE_ID needs to be defined in code.gs');
return;
}
// Set up the docs and the spreadsheet access
var copyFile = DriveApp.getFileById(TEMPLATE_ID).makeCopy(),
copyId = copyFile.getId(),
copyDoc = DocumentApp.openById(copyId),
copyBody = copyDoc.getBody(),
activeSheet = SpreadsheetApp.getActiveSheet(),
numberOfColumns = activeSheet.getLastColumn(),
activeRow = activeSheet.getRange(i, 1, 1, numberOfColumns).getValues(),
headerRow = activeSheet.getRange(1, 1, 1, numberOfColumns).getValues(),
columnIndex = 0,
fileName = activeRow[0][0] + activeRow[0][1],
pdfFile,
pdfFile2;
// Replace the keys with the spreadsheet values
for (; columnIndex < headerRow[0].length; columnIndex++) {
copyBody.replaceText('%' + headerRow[0][columnIndex] + '%',
activeRow[0][columnIndex]);
}
// Create the PDF file and delete the doc copy
copyDoc.saveAndClose();
pdfFile = DriveApp.createFile(copyFile.getAs("application/pdf"));
pdfFile2 = pdfFile.setName(fileName)
copyFile.setTrashed(true);
return pdfFile2;
}
}
The indenting clarifies a few problems:
The for loop on i is in global scope, not part of any function. It will therefore execute every time ANY function in the script is invoked, but is not explicitly invocable, as it would be in a function.
The function createPDF is declared inside that for loop. This is in global scope (see point 1), so it's still available to be called from other functions such as the menu created by your onOpen(). HOWEVER, because it's just a declaration, it is NOT invoked by the i loop! (This was the primary concern of your question.)
There's a return call inside createPdf() that is probably a left-over from the original copy of this code which produced a single PDF. Because it returns in the first time through the loop, it will STILL make a single PDF. That line needs to be moved or deleted.
return pdfFile2;
Flipping those couple of lines and deleting the return should sort us out.
var TEMPLATE_ID = '1Mxrm0kny8R7ROlBou8kSUc8dOvvH8PvtQ-EC_Nd3FUQ';
function onOpen() {
SpreadsheetApp
.getUi()
.createMenu('Create PDF')
.addItem('Create PDF', 'createPdf')
.addToUi();
}
function createPdf() {
for (var i = 2; i < 3; i++) {
if (TEMPLATE_ID === '') {
SpreadsheetApp.getUi().alert('TEMPLATE_ID needs to be defined in code.gs');
return;
}
// Set up the docs and the spreadsheet access
var copyFile = DriveApp.getFileById(TEMPLATE_ID).makeCopy(),
copyId = copyFile.getId(),
copyDoc = DocumentApp.openById(copyId),
copyBody = copyDoc.getBody(),
activeSheet = SpreadsheetApp.getActiveSheet(),
numberOfColumns = activeSheet.getLastColumn(),
activeRow = activeSheet.getRange(i, 1, 1, numberOfColumns).getValues(),
headerRow = activeSheet.getRange(1, 1, 1, numberOfColumns).getValues(),
columnIndex = 0,
fileName = activeRow[0][0] + activeRow[0][1],
pdfFile,
pdfFile2;
// Replace the keys with the spreadsheet values
for (; columnIndex < headerRow[0].length; columnIndex++) {
copyBody.replaceText('%' + headerRow[0][columnIndex] + '%',
activeRow[0][columnIndex]);
}
// Create the PDF file and delete the doc copy
copyDoc.saveAndClose();
pdfFile = DriveApp.createFile(copyFile.getAs("application/pdf"));
pdfFile2 = pdfFile.setName(fileName)
copyFile.setTrashed(true);
}
}

Adding two ints not doing anything

So the problem is, when I say ovrxp = ovrxp + xp, it never stacks and just resets every kill. A fix to this and an explanation to why this doesn't work would be much appreciated.
#EventHandler
public void onDeath(EntityDeathEvent e) {
Player player = (Player) e.getEntity().getKiller();
Skeleton s = (Skeleton) e.getEntity();
int ovrlvl = 1;
int ovrxp = 0;
Random random = new Random();
int xp = random.nextInt(30) + 21;
if (ovrlvl == 1 && ovrxp >= 200) {
player.sendMessage(ChatColor.GREEN + "You are now level two!");
player.playSound(player.getLocation(), Sound.LEVEL_UP, 1.0F, 0.0F);
ovrlvl = 2;
}
if (ovrlvl == 2 && ovrxp >= 400) {
player.sendMessage(ChatColor.GREEN + "You are now level three!");
player.playSound(player.getLocation(), Sound.LEVEL_UP, 1.0F, 0.0F);
ovrlvl = 3;
}
ovrxp = ovrxp + xp;
if (s.getCustomName() == "Undead Recruit") {
if (ovrlvl == 1) {
player.sendMessage(ChatColor.GREEN + "" + ovrxp + "/200");
}
if (ovrlvl == 2) {
player.sendMessage(ChatColor.GREEN + "" + ovrxp + "/400");
}
}
}
}
You've declared ovrxp as a local variable - it's initialized each time onDeath is called.
If you want the value to persist between multiple calls to the method, you'll need to make the variable a field (part of the object itself). Assuming the method is always called on the same object, and on the same thread, just making it an instance field should be fine.

CreateJS - Collision detection between two createjs.Containers

I currently have this working in a desktop browser but not on touch devices because I update the variables I need on mouseover. So to get around this I am trying to check for collision detection between two containers and then update the needed variables. The items should snap to the placeholder positions when a collision between the two is detected. The catch is that items and placeholders are placed dynamically any item must be able to snap to any placeholder.
var placeholders,items,selectedItem,collision,startX, startY, snapX, snapY, xpos, ypos;
var stage = new createjs.Stage("canvas");
createjs.Touch.enable(stage);
createjs.Ticker.addEventListener("tick", tick);
function init(){
xpos = 0;
ypos = 120;
container = new createjs.Container();
stage.addChild(container);
placeholders = new createjs.Container();
placeholders.name = "placeholders"
stage.addChild(placeholders);
items = new createjs.Container();
stage.addChild(items);
for(i=0;i<2;i++){
placeholder = new CustomContainer(i, "#ff0000", 100,100);
placeholder.setBounds(0,0,100,100);
placeholder.cursor = "pointer";
placeholder.x = xpos;
placeholder.name = "placeholder"+i
container.addChild(placeholder)
xpos+= (placeholder.getBounds().width + 10);
}
xpos = 0;
for(j=0;j<2;j++){
item = new CustomContainer(j, "#0000ff", 100,100);
item.active = false;
item.setBounds(0,0,100,100);
item.name = "item"+j;
item.x = xpos;
item.y = ypos;
item.startX = xpos;
item.startY = ypos;
container.addChild(item)
item.addEventListener("mousedown", selectItem);
xpos+= (item.getBounds().width + 10);
}
stage.addChild(placeholders,items);
}
function selectItem(evt) {
selectedItem = evt.target.parent;
selectedItem.mouseEnabled = false;
evt.addEventListener("mousemove", function(ev) {
moveItem(ev);
})
evt.addEventListener("mouseup", function(ev) {
selectedItem.mouseEnabled = true;
if(collision){
//New position based on the hitTest
//selectedItem.x = ;
//selectedItem.y = ;
}else{
selectedItem.x = selectedItem.startX;
selectedItem.y = selectedItem.startY;
}
})
}
function moveItem(evt){
pt = placeholders.globalToLocal(stage.mouseX, stage.mouseY);
obj = evt.target.parent;
obj.x = pt.x - 50;
obj.y = pt.y - 50;
//selectedItem collision with placeholder
collision = obj.hitTest(pt.x,pt.y)
}
function tick(evt) {
stage.update();
}
$(document).ready(init());
I am just not getting the hitTest right. You can see the working code below.
http://jsfiddle.net/non_tech_guy/2d68W/4/
The hittest will test pixel-perfect hit. I believe you're looking for a collision test.
Try this: https://github.com/olsn/Collision-Detection-for-EaselJS