Dictating Save Order of Controls in VB.Net - javascript

I have a parent page that contains a placeholder.
Span elements that contain IFrames are added to this placeholder as new IFrames are needed.
Each IFrame contains an asp control.
The parent has this code, fired onClick of the parent page:
function saveAll() {
for (i = 0; i < frames.length; i++) {
for (j = 0; j < frames[i].length; j++) {
if(frames[i][j] != null && frames[i][j] != ''){document.getElementById(frames[i][j].toString()).contentWindow.Save();}
}
}
}
which calls a save function within each control, which in turn, fires a button click, which fires the server side save function for that specific control. To someone trying to read this in 30 seconds...the previous sentence might be found to be confusing...so hopefully this might clarify the big picture here:
The problem I'm having is that the server is processing the controls out of order, despite the frames being ordered.
the frames object in the aforementioned javascript is a 2D array organized like this:
frames
[[controlA_instanceA,controlA_instanceB,controlA_instanceC],[controlB_instanceA,controlB_instanceB],
[controlC_instanceA,controlC_instanceB,etc],[etc]]
The loop, the firing of the child controls, and the frames array is all working correctly (hence why I didn't show the code here). However, could someone point me in the right direction on how to enforce the order the server processes the controls in?

Your controls need a sequence number assigned to them. Then the first step of your save all would be to decompose the 2D array into a 1D array organized by the sequence number.
When you are adding an item to the frames array you need to add them as an object with two members:
var seqNo = 0; // at some point early in the script
...
frames[x][y] = {frame: (iFrame), sequence: seqNo}; //When the Control is added
seqNo++;
where (iFrame) is the id of the frame.
Then your save all function would look like this:
function saveAll() {
var iFrames = [];
for (i = 0; i < frames.length; i++)
{
for (j = 0; j < frames[i].length; j++) {
if(frames[i][j] != null && frames[i][j] != '')
{
iFrames.push(frames[i][j]);
}
}
}
iFrames.sort(function(a,b){ return a.sequence - b.sequence});
for ( t = 0; t < iFrames.length; t++)
{
document.getElementById(iFrames[t].frame.toString()).contentWindow.Save();
}
}
In this way you are ensuring that the order is preserved because you sorted the array by the sequence number.
This is to say that the problem could be that the array appears to be sorted but it is not and and not assuming the issue is the order in which the server is responding to the click events.
EDIT:
If the server is responding to the events out of order then you may need a different approach.
If this is an ajax site and you are posting back via a web method then I would suggest creating a new web method that takes an array as a parameter.
Push all the content you wish to save into the array and then pass it back to the server for processing in a specific order.
If this is a classic forms site then you can handle a custom postback in your page load event.
Either way it sounds like you need to re-evaluate the way this is processing.

Related

Javascript/event-handlers - code keeps looping

I don't exactly know how to formulate the question. Below I will describe what I am doing and what unintended consequences are encountered.
I am creating a to-do list, I found the design and functionality in a youtube video. Here is the code so far: https://jsfiddle.net/savvyd/9bu65kso/ .
Tl:dr: this is what I was recreating, mess around with it and you'll quickly understand the functionality https://codingnepalweb.com/demos/todo-list-app-javascript/.
What my method of mimicking the functionality was:
There are three sections in the to-do list: 1. all items, 2. pending items and 3. completed items. When the user clicks on a checkbox there results a behavior, either moving the box to pending or to completed sections. My idea was to attach event handlers to the list items : all, pending and completed, after the user has manipulated the checkboxes to their desire, the event-handlers were intending to 1.collect the current state of the board (after manipulation), delete the previous state of the board and create anew the following correct state of the board.
However, my code goes on an endless loop in this section :
for (let j = 0; j < box.length; j++) {
console.log(j);
console.log(box.length);
let name = box[j].querySelector("p").innerText;
let list = document.querySelector(".all");
let type = box[j].classList.contains("checked") ? "checked" : "unchecked";
boardModel.spawnPattern(name, list, type);
}
Furthemore if the below code was running, it would have a consequence of erasing the box array which was intended to capture the following state of the board.
// for (let i = 0; i < boardModel.textContainer.length; i++) {
// boardModel.removeAllChildNodes(boardModel.textContainer[i]);
// }
// boardModel.allowErase = false;
Is this a problem with event-handlers? Thank you.

Reordering/move pages using Indesign script

I have a nearly 400 page document that I need to [randomly] reorder the pages. (If you need to know, this is a book of single page stories that need to be randomly distributed. I created a random list of pages to input into the script.)
I've been working with a modified script I found elsewhere on the internet that creates an array and moves the pages around:
var order="...list of new page numbers...";
// Create an array out of the list:
ranges = toSeparate (order);
if (ranges.length != app.activeDocument.pages.length)
{
alert ("Page number mismatch -- "+ranges.length+" given, "+app.activeDocument.pages.length+" in document");
exit(0);
}
// Consistency check:
sorted = ranges.slice().sort(numericSort);
for (a=0; a<sorted.length-1; a++)
{
if (sorted[a] < sorted[a+1]-1 ||
sorted[a] == sorted[a+1])
alert ("Mismatch from "+sorted[a]+" to "+sorted[a+1]);
}
// alert ("New order for "+order+"\nis "+ranges.join(", "));
// Convert from 1..x to 0..x-1:
for (moveThis=0; moveThis<ranges.length; moveThis++)
ranges[moveThis]--;
for (moveThis=0; moveThis<ranges.length; moveThis++)
{
if (moveThis != ranges[moveThis])
{
try{
app.activeDocument.pages[ranges[moveThis]].move (LocationOptions.BEFORE, app.activeDocument.pages[moveThis]);
} catch(_) { alert ("problem with page "+moveThis+"/index "+ranges[moveThis]); }
}
for (updateRest=moveThis+1; updateRest<ranges.length; updateRest++)
if (ranges[updateRest] < ranges[moveThis])
ranges[updateRest]++;
}
function toSeparate (list)
{
s = list.split(",");
for (l=0; l<s.length; l++)
{
try {
if (s[l].indexOf("-") > -1)
{
indexes = s[l].split("-");
from = Number(indexes[0]);
to = Number(indexes[indexes.length-1]);
if (from >= to)
{
alert ("Cannot create a range from "+from+" to "+to+"!");
exit(0);
}
s[l] = from;
while (from < to)
s.splice (++l,0,++from);
}} catch(_){}
}
// s.sort (numericSort);
return s;
}
function numericSort(a,b)
{
return Number(a) - Number(b);
}
This code worked, except that it was consistently rearranging them into the wrong random order, which, at the end of the day, is workable, but it'll just be a bigger pain in the ass to index the stories.
I suspected the problem might be caused by starting at the begginning of the document rather than the end, so I modified the script to start at the end, but then app.activeDocument.pages[ranges[moveThis]] kept coming up as undefined.
So I gave up and tried this:
app.activeDocument.pages[298].move (LocationOptions.BEFORE, app.activeDocument.pages[366]);
app.activeDocument.pages[33].move (LocationOptions.BEFORE, app.activeDocument.pages[365]);
app.activeDocument.pages[292].move (LocationOptions.BEFORE, app.activeDocument.pages[364]);
And so on for every page. (This reminds me of my time in junior high using sendKeys to create programs in Visual Basic. Had I bothered to seriously learn JavaScript instead of creating shitty AOL chatroom scrollers, I probably wouldn't be on here today.)
Nevertheless, I received the following error:
Error Number: 30477
Error String: Invalid value for parameter 'reference' of method 'move'. Expected Page or Spread, but received nothing.
I'm trying to avoid having to manually move the pages, especially considering the amount of time I've already been working on this. Any suggestions on what I need to change? Thank you!
The issue might be that you are using more than one page per spread and then trying to shuffle them across spread. The better way is to use single page per spread.
Here is a small snippet that works on my machine
var doc = app.activeDocument;
doc.documentPreferences.facingPages = false;
for (var i =0; i < 100; i++){
var index = parseInt((Math.random() * doc.spreads.length) % doc.spreads.length + '' , 10);
doc.spreads[index].move();
}
What this does is
Disables the facing pages options and makes one page per spread. A desirable condition as you mentioned that your stories are one page each(I am assuming that your stories will not violate this assumption).
Takes a random spread from the doc and sends it to the end of the spreads in the doc. It does so 100 times.
The result is what you wanted. A script to shuffle the current SPREADS randomly.

Set Qualtrics Embedded Data with Javascript for loop

I am working on a survey in qualtrics, and need to be able to set many embedded data fields with different values, depending on a random selection of the experimental condition.
In the Survey Flow, I've entered all the names of the desired embedded data values.
I want this code to execute at the start of the survey, and to go through and set the values of those Embedded data variables.
The reason I use a for loop is because the variables are named things like:
set1a
set1b
set1c
var condition = Math.floor((Math.random() * 3) + 1)
var conditions =[ [8,8,8,5,5,5,5,2,2,2], [8,8,8,7,7,7,7,2,2,2], [10,10,10,5,5,5,5,2,2,2], [10,10,10,7,7,7,7,2,2,2]]
var values = condition[conditions]
var letters ="abcdefghij"
Qualtrics.SurveyEngine.addOnload(function(values)
{
for (var i = 0; i < values.length; i++ ) {
var dataname = "set1" + letters.charAt(i)
Qualtrics.SurveyEngine.setEmbeddedData(dataname,values[i]);
}
});
However, this code doesn't work.
When I try to call the variables using piped text later on in the survey (after a page break) they do not appear to have stored.
You have two issues.
First, you can only set Javascript in Qualtrics if it's inside of the .addOnload function, e.g.:
Qualtrics.SurveyEngine.addOnload(function(values)
{
// Your code
});
Second, your method for assigning - values - throws an error message.
Qualtrics doesn't have an issue saving embedded data in a for loop, so if you fix these two points, you should be good to go.

JS For Loop Stopping Early after Calling Function

I have a Javascript Array that holds the contents of a page. In order to draw all the objects in the right places when the page loads I loop over the array and pull out the elements. This worked very well until I allowed the objects to have children within them.
The current array structure is
0-> {elements=[] frame={I keep the frame attributes here with key value pairs}}, 1-> {elements=[] frame={}}
However, I just started adding sub-elements to the elements array in each object. So now I have to loop through/draw each element, check to see if there are any children and if so then I have to draw them too.
The problem I'm having is that after I loop through the first 0 object and it's children the for loop stops running. Is it because I'm calling the same function multiple times? I've done that before so I don't think that's what is happening.
this.run_loop = function (spawn, dom) {
console.log(spawn)
alert(spawn.length)
for (i = 0; i < spawn.length; i++) {
console.log(spawn[i])
//alert("i one")
var newdom = dom + "_" + i;
this.synthesize_elements(spawn[i], dom, newdom)
if (spawn[i].hasOwnProperty('elements')) {
//alert("FOUND")
var newarray = spawn[i]['elements'];
if (newarray.length > 0) {
this.run_loop(newarray, newdom)
}
}
}
}
This is a little old but I encountered a similar issue and found my way here, but I figured it out and thought I'd post the solution if anyone else came across this. The issue in my case (and it looks like in your case as well though I can't be sure) was in the declaration of the for loop:
for (i = 0; i < spawn.length; i++)
You're not declaring that i is a new var. so if anything inside the
this.run_loop(newarray, newdom)
function also manipulates a counter variable called i that isn't declared a new var, it will also change the one in your outer scope, and kick you out of the loop if it goes over the length of spawn
just always declare:
for (var i; i< spawn.length; i++)
in your loops or make sure your counters are unique.

Algorithm design for a js loop structure

I got an array [1,2,3,4]
I need first to run over [2] that was chosen, set his styles, and than after run over the other children and reset their styles.
At the moment, my algorithm is as following:
for item in array
if item == chosenEl
set chosen classes
for item in array
if item != chosenEl
reset chosen classes for the rest of the children
Or coffe:
for item in #array
if item.element is element
item.selected = true
item.element.classList.add #selectedClass
item.element.focus()
for item in #array
if item.element isnt element
item.selected = false
item.element.classList.remove #selectedClass
I need to design the function like that, and not as a simple forElse loop, due to some restrictions in me framework.
How can I improve this code?
Thank you.
Explanation- The reason I need this design, is due to duplicated calls for 2 different functions, that conflict one the other.
I'm developing an app for LG TV. The LG TV has its own libraries. Now in my function I set the styles of chosen elements. Byt when I focus to the chosen element, I activate the LG TV onFocus listener, which in his turn control the selected styles.
So when I loop the second or third child, I set again the selected styles, of cleared elements. TLDR but thats how the loops conflicting each other. One interrupting the work of other.
The code was not written by me. I entered an existing project, and I havent written this function, so i cannot just remove the Focus() function.
Instead of looping twice, consider below code
for item in array
{
if item == chosenEl
{
set chosen classes
continue; <--use this to return to next iteration without executing next statements
}
reset chosen classes for the rest of the children
}
It will be O(n) instead of O(n) + O(n)
Edit:
I am sorry, I didn't understand your explanation. If all you need is a function which you can repeatedly call then here it is, call resetStyles multiple times by passing selected value. Please note since you haven't provided exact data types, I assumed them as integers.
<script>
var resetStyles = function(selecteditem)
{
var arr = [1,2,3,4];
for(var i=0; i < arr.length; i++)
{
if(arr[i] == selecteditem)
{
//set class here
continue;
}
//remove class here
}
};
resetStyles(2);//call this by changing the values
</script>
Why are you looping twice? Far easier to just do:
for( var i=0, l=array.length; i<l; i++) {
if( item == chosenEl) {
// set styles
}
else {
// clear styles
}
}

Categories

Resources