Extendscript: how to skip current iteration in a for loop? - javascript

I have the following code, written in ExtendScript to process a series of layers in an After Effects composition:
for (var i=0; i < selectedLayers.length; i++) {
var layer = selectedLayers[i];
if (!layer.hasVideo || !layer.enabled) {
//Go for the next one
continue;
}
//Do stuff
}
If an element isn't enabled or doesn't have video in it, the loop should skip it; if it does, then it should be processed.
Now, everything works fine if there are no elements that fulfill that "if" check, but if one element fulfills that check… then the loop gets stuck at the next iteration. That is: imagine if the element at i=2 doesn't have video. The "continue" gets executed… and then, the loop gets stuck indefinitely at i=3 and never ends.
Why does this happen? I thought that "continue" is precisely the instruction to skip an iteration of a loop in Javascript/Extendscript. What's going on?
EDIT: as requested, here is my entire code. Maybe I forgot a brace somewhere in one of those nested "if"s… but in that case, how can the code work in some cases and not in others?
var nombreDelPlugin="Denoiser II";
var rutaRender="/Users/paulj";
var activeItem = app.project.activeItem;
if ((activeItem == null) || !(activeItem instanceof CompItem)) {
alert("Please select or open a composition first.");
}
else {
var selectedLayers = activeItem.selectedLayers;
if (activeItem.selectedLayers.length == 0) {
alert("Please select at least one layer in the active comp first.");
}
else {
var comp = app.project.activeItem;
var width=comp.width;
var height=comp.height;
var par=comp.pixelAspect;
var fps=comp.frameRate;
var tempFolder = comp.parentFolder.items.addFolder(comp.name + " - Temp Comps");
var ClipsAnadidos=Array();
var nombresUsados={};
for (var i=0; i < selectedLayers.length; i++) {
alert("Mooo: " + i);
var layer = selectedLayers[i];
if (!layer.hasVideo || !layer.enabled) {
alert("Meeept: " + i);
continue;
}
/* if (!esFootage(layer)) {
alert("Meeept: " + i);
break;
}
*/
//¿Hemos renderizado ya este layer? Si es así, nos lo saltamos.
var original=layer.source;
if (inArray(original, ClipsAnadidos) > 0) {
continue;
}
ClipsAnadidos.push(original);
//¿Hay otra comp ya con este mismo nombre?
var vecesUsado=nombresUsados[original.name];
if (!vecesUsado) { vecesUsado=0; }
var nombre= original.name + "_" + vecesUsado;
nombresUsados[original.name]=vecesUsado + 1;
//Creamos la nueva comp con el clip dentro
var newcomp=app.project.items.addComp(nombre, width, height, par, original.duration, fps);
var newlayer=newcomp.layers.add(original, original.duration);
newcomp.parentFolder=tempFolder;
//Si la escala no es 100, usamos la de la comp original
if ((layer.scale.value[0] != 100) || (layer.scale.value[1] != 100)) {
newlayer.scale = layer.scale.value;
}
var denoise = newlayer.property("Effects").addProperty(nombreDelPlugin);
//Añadimos al render queue, y establecemos la ruta de salida
var rqi = app.project.renderQueue.items.add(newcomp);
var om = rqi.outputModule(1); // Assumes at least one output module
om.file=new File(rutaRender + "/" + original.name);
}
}
}
function esFootage(lay) {
if (lay.source instanceof FootageItem) {
//alert(lay.name + " es footage");
if (lay.source.mainSource instanceof SolidSource) { return false; }
else { return true; }
}
if (lay.source instanceof CompItem) {
return true;
}
else { return false; }
}
function inArray(v, arr) {
for (i=0; i < arr.length; i++) {
if (arr[i] == v) { return i; }
}
return -1;
}

This works fine for me:
var selectedLayers = [
{hasVideo: true, enabled: true},
{hasVideo: true, enabled: true},
{hasVideo: true, enabled: false},
{hasVideo: true, enabled: true},
{hasVideo: false, enabled: true}
];
for (var i=0; i < selectedLayers.length; i++) {
var layer = selectedLayers[i];
if (!layer.hasVideo || !layer.enabled) {
//Go for the next one
continue;
}
//Do stuff
console.log(i);
}
It skips 2 and 4 and outputs:
0
1
3
If you have a loop within a loop it could be that the inner i is being reset, which in that case you'd have to define it outside of the loops.

Related

JavaScript function dosen't work correct

I have a function that checking board is there a searching element.
First script creating a board with different elements. Element in the square next to board is element that user has to find on the board and click them.
User has to click (as quick as possible) all searching elements. After click on element function checking a board, is there more elements. If yes then nothing happen and user has to click another one. If on board there isn’t searching elements then function display a time and new board create.
But some reason function works correct only first time after page load. Latter function ignore more then one element on board or see element that doesn’t exist on board any more.
Can you tell me what is wrong.
Part of code bellow and there is a link to testing page.
http://doomini2.linuxpl.info/font/
Thank you
function secondStage() {
createBoxes(59);
var usingSet = [];
var i = 0;
var boxList = document.querySelectorAll("#board > div");
createSet(usingSet, 20, shapes);
(function paint() {
if (i <= 59) {
var curentBox = boxList[i];
curentBox.className = usingSet[draw(20)];
curentBox.style.color = colors[draw(colors.length - 5)];
timeStop = setTimeout(paint, 50);
i++;
} else {
var findShape = boxList[draw(59)];
toFind.className = findShape.className;
toFind.style.color = findShape.style.color;
findBoxes(boxList);
clearTimeout(timeStop);
}
})();
}
//function checks boxes to find a proper shape
function findBoxes(boxList) {
startTime = Date.now();
board.addEventListener("mousedown", function (e) {
if ((e.target.className === toFind.className)) {
e.target.className = "correct";
e.target.innerHTML = "OK";
checkBoard();
} else if (e.target.id === "board" || e.target.className === "correct") {
} else {
e.target.className = "false";
e.target.innerHTML = "NO";
}
}, false);
function checkBoard() {
var condition = false;
console.log(condition);
for (var x = 0; x < boxList.length; x++) {
if ((boxList[x].className === toFind.className)) {
condition = true;
console.log(condition);
}
}
if (condition === false) {
var clickTime = Date.now();
var timeResult = parseFloat(((clickTime - startTime) / 1000).toFixed(3));
lastResult.innerHTML = timeResult + "s";
secondResult[secondResult.length] = timeResult;
console.log(secondResult);
displayResult(secondStage);
}
}
}
//function displaig results after every single round
function displayResult(stage) {
cover.className = "";
TweenMax.to("#lastResultDiv", 1, {ease: Back.easeOut, right: (winWidth / 4), });
TweenMax.to("#go", 1, {ease: Back.easeOut, top: (winWidth / 3), onComplete: function () {
goButton.addEventListener("click", function () {
clear();
}, false);
}});
//clear board and return to play
function clear() {
TweenMax.to("#lastResultDiv", 1, {ease: Back.easeIn, right: winWidth, });
TweenMax.to("#go", 1, {ease: Back.easeOut, top: -100, onComplete: function () {
cover.className = "hide";
lastResultDiv.style.right = "-592px";
toFind.className = "";
board.innerHTML = "";
if (firstStageRound === 10) {
secondStage();
} else if (secondStageRound === 5) {
thirdStage();
} else {
stage();
}
}});
}
}
Not Load this File http://cdnjs.cloudflare.com/ajax/libs/gsap/1.17.0/TweenMax.min.js
try to local path

Java Script: how to create test case from given input

I am in need of help. I have to create test cases from excel which is below format:
**Current NextState Function Type**
GREETING-1,repeat,PMSG
REPEAT,CallerType,PMSG
CALLERTYPE,XferBridges(DTMF:1),ClaimMenu(DTMF:2),XferLine2(DTMF:3),XferLine2(DTMF:4),Menu
CLAIMMENU,RejectMenu(DTMF:1),XferLine2(DTMF:2),Menu
REJECTMENU,NotCovered(DTMF:1),Terminated(DTMF:2),NMCard(DTMF:3),NMGroup(DTMF:4),Refill(DTMF:5),NoDrugNDC(DTMF:6),XferLine2(DTMF:2),Menu
NOTCOVERED,RejectMenu(DTMF:1),Menu
TERMINATED,XferLine2(DTMF:1),Menu
NMCARD,XferLine2(DTMF:1),Menu
NMGROUP,XferLine2(DTMF:1),Menu
REFILL,XferLine2(DTMF:1),Menu
NODRUGNDC,XferLine2(DTMF:1),Menu
XFERBRIDGES,STOP,PMSG
XFERLINE2,STOP,PMSG
THANKYOU,GoodBye,PMSG
GOODBYE,STOP,PMSG
The tool will generate n number of test cases. Please guide me what code I shall write which can generate below type test case:
Case 1: Greeting-1 -> Repeat -> CallerType, Press DTMF 1 ->XferBridges ->STOP
Case 2: Greeting-1 -> Repeat -> CallerType, Press DTMF 2 ->ClaimMenu, Press DTMF 1 -> RejectMenu, Press DTMF 1 ->NotCovered, Press DTMF1 -> RejectMenu -> STOP( from entering infinte into loop)
Case 3: Greeting-1 -> Repeat -> CallerType, Press DTMF 2 ->ClaimMenu, Press DTMF 1 -> RejectMenu, Press DTMF 2 -> Terminated, Press DTMF 1 ->XferLine2 ->STOP
Case 4: Greeting-1 -> Repeat -> CallerType, Press DTMF 2 ->ClaimMenu, Press DTMF 1 -> RejectMenu, Press DTMF 3 -> NMCard, Press DTMF 1 ->XferLine2 ->STOP
**.**
**.**
and so on
You might have got an idea what I am doing here. Trying to create test cases for each call flow, if next state is PMSG then adding it to the same array, but if next state is MENU then creating new array( which means new test case) which will be going through all DTMF option and its corresponding next state and so on
I used recursive loop to get output, but it's giving wrong values.
Code:
function generateTestCaseList(nextState) {
var incCount = 1;
var positionInt = findNextState(nextState);
var tempStoredArray = allState[positionInt];
if(tempStoredArray[0].toLowerCase() == menuName.toLowerCase())
{
incCount = menuPostion;
f = true;
}
else if(tempStoredArray[0].toLowerCase() == nextMenuName.toLowerCase())
incCount = nextMenuPostion;
var tempStr = getState(tempStoredArray, incCount);
var tempArr = tempStr.toLowerCase().split("%");
nextState = tempArr[1];
parentStr = parentStr + tempArr[0];
var cntInfi = parentStr.toLowerCase().split(nextState).length -1;
if(cntInfi == 2)
{
return parentStr;
}
else if(nextState != "stop")
{
var pstInt = findNextState(nextState);
var tempArr = allState[pstInt];
if(tempArr[tempArr.length -1] == "Menu" && f == true)
{
nextMenuName = tempArr[0];
var tempMenuPsx= tempArr.length - 2;
//WScript.Echo("tempMenuPsx"+nextMenuName+tempMenuPsx);
for(var k=tempMenuPsx;k >0 ;k--)
{
nextMenuPostion = k;
//WScript.Echo("nextMenuPostion"+nextMenuPostion);
WScript.Echo("parentStr"+parentStr);
var temp = generateTestCaseList(nextState);
childStr = childStr +temp;
resultList.push(childStr);
childStr = "";
}
}
else
{
generateTestCaseList(nextState);
}
}
else
{
return parentStr;
}
}
function findNextState(nextState) {
for(var l=0;l<allState.length;l++)
{
if(allState[l][0].toLowerCase()==nextState.toLowerCase())
return l;
}
return 0;
}
function getState(tempArray,l) {
var tempStr = tempArray[0];
if(tempArray[2] =="GETV")
tempStr = tempStr +";Voice: Say Something;"+tempArray[2]+";$%"+tempArray[1];
else if(tempArray[2] =="PMSG")
tempStr = tempStr +";"+tempArray[2]+";$%"+tempArray[1];
else
tempStr = tempStr +";DTMF:"+l+";"+tempArray[tempArray.length -1]+";$%"+tempArray[l];
return tempStr;
}
result( "$" is next state separator here):
1. greeting-1;pmsg;$repeat;pmsg;$callertype;dtmf:4;menu;$xferline2;pmsg;$
2. greeting-1;pmsg;$repeat;pmsg;$callertype;dtmf:3;menu;$xferline2;pmsg;$
3. greeting-1;pmsg;$repeat;pmsg;$callertype;dtmf:2;menu;$claimmenu;dtmf:2;menu;$xferline2;pmsg;$claimmenu;dtmf:1;menu;$rejectmenu;dtmf:7;menu;$xferline2;pmsg;$rejectmenu;dtmf:6;menu;$nodrugndc;dtmf:1;menu;$
4. greeting-1;pmsg;$repeat;pmsg;$callertype;dtmf:2;menu;$claimmenu;dtmf:2;menu;$xferline2;pmsg;$claimmenu;dtmf:1;menu;$rejectmenu;dtmf:7;menu;$xferline2;pmsg;$rejectmenu;dtmf:6;menu;$nodrugndc;dtmf:1;menu;$rejectmenu;dtmf:1;menu;$notcovered;dtmf:1;menu;$rejectmenu;dtmf:7;menu;$
5. greeting-1;pmsg;$repeat;pmsg;$callertype;dtmf:2;menu;$claimmenu;dtmf:2;menu;$xferline2;pmsg;$claimmenu;dtmf:1;menu;$rejectmenu;dtmf:7;menu;$xferline2;pmsg;$rejectmenu;dtmf:6;menu;$nodrugndc;dtmf:1;menu;$rejectmenu;dtmf:1;menu;$notcovered;dtmf:1;menu;$rejectmenu;dtmf:7;menu;$rejectmenu;dtmf:6;menu;$nodrugndc;dtmf:1;menu;$
The output contain all DTMF option in single call flow which is worng.
Any input will ge great help.
I have got the solution, it's not efficient but does give the desired output.
function generateTestPlan() {
var menuCount = 0;
for(var g=0;g<allState.length;g++)
{
var tempArr = allState[g];
if(tempArr[tempArr.length-1] == "Menu")
{
var tempArr = [];
tempArr.push(allState[g][0]);
for(var i =1;i<allState[g].length-1; i++)
{
tempArr.push(allState[g][i]);
menuCount++;
}
menuList.push(tempArr);
}
}
var firstState = allState[0][0];
for(var k=0;k < menuCount*1000;k++)
{
getCallFlow(firstState,stack1)
stack.push(stack1);
stack1 = [];
}
stack = eliminateDuplicates(stack);
}
function getCallFlow (nextState,stack1)
{
var positionInt = findNextState(nextState);
var tempStoredArray = allState[positionInt];
var g = 0;
for(var b= 0; b < menuList.length ;b++)
{
if(menuList[b][0] == tempStoredArray[0])
{
var len = menuList[b].length -1;
g =Math.floor(Math.random() * len) + 1 ;
}
}
var tempStr = getState(tempStoredArray,g);
var tempArr = tempStr.toLowerCase().split("%");
var nextState1 = "";
var multipleGoto = tempArr[1].toLowerCase().split("#").length -1;
if(multipleGoto > 1)
{
var multipleArray = tempArr[1].toLowerCase().split("#");
//WScript.Echo(multipleArray)
var len = multipleArray.length -1;
var choose =Math.floor(Math.random() * len) + 1 ;
//WScript.Echo(choose)
nextState1 = multipleArray[choose];
//WScript.Echo(nextState1)
}
else
{
nextState1 = tempArr[1];
}
stack1.push(tempArr[0]);
if(checkIfArrayIsUnique(stack1) == false)
{
stack1.push("stop");
return ;
}
if(nextState1 == "stop")
{
stack1.push("stop");
return ;
}
else
{
getCallFlow(nextState1,stack1);
}
}
function findNextState(nextState) {
for(var l=0;l<allState.length;l++)
{
if(allState[l][0].toLowerCase()==nextState.toLowerCase())
return l;
}
return 0;
}

Central JS Timer

Looking at Secrets of the JavaScript Ninja, I took this code for a "Central Timer":
var timers = {
timerID: 0,
timers: [],
add: function(fn) {
this.timers.push(fn);
},
start: function() {
if(this.timerID) return;
(function runNext() {
if(timers.timers.length > 0) {
for (var i = 0; i < timers.length; i++) {
if(timers.timers[i]() === false) {
timers.timers.splice(i,1);
i--;
}
}
console.log("setting timeout.");
timers.timerID = setTimeout(runNext, 0);
}
})();
},
stop: function() {
clearTimeout(this.timerID);
this.timerID = 0;
}
};
Then, test it out.
var box = document.getElementById("box"), x = 0, y = 20;
timers.add(function() {
box.style.left = x + "px";
log.console("x:", x);
if(++x > 50) return false;
});
timers.add(function() {
box.style.top = y + "px";
y += 2;
log.console("y:", y);
if (++y > 120) return false;
});
console.log("starting timer.");
But, looking at my console, I see setting timeout scrolling endlessly without any increment to x or y.
What's going on here?
JsFiddle
EDIT Page # - 210/394.
Note - it's possible I made a copy/paste mistake - not blaming.
timers.length is undefined in the for loop in runNext, so the code does not actually iterate over the intended array. Either you transcribed it incorrectly or the code in the book has a bug. Regardless, this is the correct loop:
// ↓↓↓↓↓↓↓
for (var i = 0; i < timers.timers.length; i++) {
if(timers.timers[i]() === false) {
timers.timers.splice(i,1);
i--;
}
}
Fiddle

How do I retrieve array elements in pairs using the for loop in javascript?

I created an empty array which has to be filled by the website user with the input form. The user can input any number of elements (in this case, friends) he/she wants, but the total has to be an even number.
After using the sort() method in the array (to shuffle the initial order set by the input), I need to form pairs with its elements and print it on the site.
I tried to do this using the for-loop but I can only retrieve one element at once.
¿Is there a way to do it?
Thanks in advance!
var lista = [];
function muestraNombres(){
var x = $("#amigo").val();
if(x == ""){
alert("ingresa bien los datos");
}else{
lista.push(x);
$("#listado").append('<div id="otrodiv">' + x + '</div>');
$("#amigo").val('');
}
}
function recuperaNombres (){
if (lista.length%2 != 0) {
alert("Debes ingresar otro amigo para realizar los pares");
}else{
amigoSecreto();
}
}
function amigoSecreto(){
$("#listado").hide();
shuffle();
generaPares();
}
function shuffle (){
lista.sort(function() {return 0.5 - Math.random() })
}
function generaPares (){
for (var i=0; i<lista.length;i++){
$("#resultado").append('<div id="otrodiv1">' + lista[i] + '</div>')
}
$("#reiniciar").show();
$("#parear").hide();
$("#ingresar").hide();
}
for (var idx=0; idx < arr.length; idx += 2) {
arr[idx]; // is first element in pair
arr[idx+1]; // is second element in pair
}
Javascript makes it very simple to create objects on-the-fly, you can do something like this :
var friendsArray = [];
// let's put some values in the array
// using plain simple object notation
friendsArray.push( { name : 'stan', friendName : 'kyle' } ) ;
friendsArray.push( { name : 'stan', friendName : 'eric' } ) ;
friendsArray.push( { name : 'butters', friendName : 'kenny' } ) ;
// let's print the array
for (var i=0; i<friendsArray.length; i++) {
var thisFriend = friendsArray[i];
console.log(thisFriend.name + ' has ' + thisFriend.friendName + ' as a friend ');
}
// output is :
// "stan has kyle as a friend "
// "stan has eric as a friend "
// "butters has kenny as a friend "

javascript countdown with showing milliseconds

I want to do a count down and want to show like format as Minutes:Seconds:Milliseconds. I made a count down with jquery plug-in countdown but it shows just Minutes:Seconds format.
Is there any way to make it right?
Many Thanks!
Hi guys I have developed a code for my self use the following code
counter for 20 seconds
var _STOP =0;
var value=1999;
function settimer()
{
var svalue = value.toString();
if(svalue.length == 3)
svalue = '0'+svalue;
else if(svalue.length == 2)
svalue = '00'+svalue;
else if(svalue.length == 1)
svalue = '000'+svalue;
else if(value == 0)
svalue = '0000';
document.getElementById('cn1').innerHTML = svalue[0];
document.getElementById('cn2').innerHTML = svalue[1];
document.getElementById('cn3').innerHTML = svalue[2];
document.getElementById('cn4').innerHTML = svalue[3];
value--;
if (_STOP==0 && value>=0) setTimeout("settimer();", 10);
}
setTimeout("settimer()", 10);
Try this: http://jsfiddle.net/aamir/TaHtz/76/
HTML:
<div id="timer"></div>
​
JS:
var el = document.getElementById('timer');
var milliSecondsTime = 10000;
var timer;
el.innerHTML = milliSecondsTime/1000;
timer = setInterval(function(){
milliSecondsTime = milliSecondsTime - 1000;
if(milliSecondsTime/1000 == 0) {
clearTimeout(timer);
el.innerHTML = 'BOOOOM';
}
else {
el.innerHTML = milliSecondsTime/1000;
}
},1000);
​
If you want to make your own timer.
read this earlier question
How to create a JQuery Clock / Timer
Try setting the format parameter - http://keith-wood.name/countdownRef.html#format
On further reading, this plugin doesn't do milliseconds. At this point, you either have to edit the actual plugin code or find a new plugin.
I completely agree with #Matt Ball's comment.It may also cause the browser to crash.
Why don't you try this solution instead
jQuery 1 minute countdown with milliseconds and callback
I did it like this (generic counter from N to X (X > N)):
var dynamicCounterAddNewValue = 20;
var currentDynamicUpdater;
function dynamicCounterForValueForControlUpdater(_updaterData) {
_updaterData.from += dynamicCounterAddNewValue;
if (_updaterData.from > _updaterData.to) {
_updaterData.from = _updaterData.to;
}
_updaterData.c.html(_updaterData.from.toString());
if (_updaterData.from < _updaterData.to) {
currentDynamicUpdater = setTimeout(
dynamicCounterForValueForControlUpdater,
10,
{
c: _updaterData.c,
from: _updaterData.from,
to: _updaterData.to
}
);
}
else {
clearTimeout(currentDynamicUpdater);
}
return;
}
// _c -> jQuery object (div,span)
// _from -> starting number
// _to -> ending number
function dynamicCounterForValueForControl(_c, _from, _to) {
clearTimeout(currentDynamicUpdater);
dynamicCounterForValueForControlUpdater(
{
c: _c,
from: _from,
to: _to
}
);
return;
}
EDIT: Updated version (more flexible - for N elements one after another):
(input element is Array of elements for making them dynamic-counts)
var dynamicCounterTimeout = 10;
var currentDynamicUpdater;
function odcArray(_odca) {
this.odca = _odca;
return;
}
function odc(_c, _from, _to) {
this.c = _c; // $('#control_id')
this.from = _from; // e.g. N
this.to = _to; // e.g. M => (M >= N)
var di = parseInt(_to / 45, 10);
if (di < 1) {
di = 1;
}
this.dynamicInc = di;
return;
}
function dynamicCounterForValueForControlUpdater(_odca) {
if (
_odca.odca === null
||
!_odca.odca.length
) {
clearTimeout(currentDynamicUpdater);
return;
}
var o = _odca.odca[0];
o.from += o.dynamicInc;
if (o.from > o.to) {
o.from = o.to;
_odca.odca.shift(); // Remove first element
}
o.c.html(o.from.toString());
currentDynamicUpdater = setTimeout(
dynamicCounterForValueForControlUpdater,
dynamicCounterTimeout,
_odca
);
return;
}
function dynamicCounterForValueForControl(_odca) {
clearTimeout(currentDynamicUpdater);
// SETUP all counters to default
for (var i = 0; i < _odca.odca.length; i++) {
_odca.odca[i].c.html(_odca.odca[i].from.toString());
}
dynamicCounterForValueForControlUpdater(
_odca
);
return;
}

Categories