1

I have an xpage, where fields are created dynamically. By default, there are 3, but you can click a button to add as many as you like, naming convention "ObjectiveDetails1", "ObjectiveDetails2" and so on.

I am trying to handle blank fields... For example, there is content in fields 1 and 2, nothing in 3 and 4, but content in 5. What I want to do, is shift content from field 5 into the first available blank, in this case 3. Likewise, if there is content in fields 1, 2, 4, 5, I then need content in 4, to go into field 3, and content in 5 to go into field 4 etc. At the moment, I'm managing to shift content up 1 only.

So if fields 2, 3, 4 are blank but 5 has content, it only moves the content into 4, where-as I need it to move into field 2.

I hope I've explained this well enough..... Current code is a little messy....

for (var i = 1; i < viewScope.rows+1; i++) {
print("Starting Array.....");
if(applicationScope.get("BreakAllCode")==true){
  break;
}
var objFieldName:string = "ObjectiveDetails" +i;
print ("Field Name: " + objFieldName);

var fieldValue = document1.getItemValueString(objFieldName);

print ("Field Value: " + fieldValue);
if (fieldValue =="" || fieldValue==null){
    print("EMPTY"); 

    // We now need to delete the 3 fields related to this objective
    var updFieldName:string = "ObjectiveUpdates" +i;
    var SAFieldName:string = "ObjectiveSelfAssessment" +i;

    // Before we delete the fields, we need to check if the next field is blank
    // and if not, copy its contents into this field.

    for (var n =i+1; n < viewScope.rows+1; n++) {
    if(applicationScope.get("BreakAllCode")==true){
     break;
    }

        if(document1.hasItem("ObjectiveDetails" +n)){       
            print("Next field: " +"ObjectiveDetails" +n);
            var nextFieldValue = document1.getItemValueString("ObjectiveDetails" +n);

            if (!nextFieldValue =="" || !nextFieldValue==null){
                // Now copy the content into the field
                var nextFieldName:string = "ObjectiveDetails" +n;
                var previousNo = n-1;
                var previousFieldName:string = "ObjectiveDetails" +previousNo;
                print ("Previous field: " + previousFieldName);
                document1.replaceItemValue(previousFieldName,nextFieldValue);

                // Now clear the content from next field
                document1.replaceItemValue(nextFieldName,"");
            }else{
                // Do nothing
            }
        }else{
            print("Last field");
        }
    }
    // Remove items from the document
    //document1.removeItem(objFieldName);
    //document1.removeItem(updFieldName);
    //document1.removeItem(SAFieldName);

    // Remove fields from our arrays
    //viewScope.fields.splice(i-1, 1);
    //viewScope.fields2.splice(i-1, 1);
    //viewScope.fields3.splice(i-1, 1);

    // Update the row variable
    //viewScope.rows--;
    //document1.replaceItemValue("rows",viewScope.rows);
    //document1.save();

    // We now need to "re-index" the array so that the fields are numbered corectly

}else{
    print("We have a value");
}
}

Update with beforePageLoad:

viewScope.rows = document1.getItemValueInteger("rows");

var rowCount:integer = viewScope.rows;
var newCount:integer = 0;

while(newCount<rowCount){
if (!viewScope.fields) {
    viewScope.fields = [];
    viewScope.fields2 = [];
    viewScope.fields3 = [];
}

viewScope.fields.push("ObjectiveDetails" + (viewScope.fields.length + 1));
viewScope.fields2.push("ObjectiveUpdates" +  (viewScope.fields2.length + 1));
viewScope.fields3.push("ObjectiveSelfAssessment" +  (viewScope.fields3.length + 1));

newCount++;
}
Chris Richards
  • 695
  • 5
  • 14

2 Answers2

2

If I understood your problem correctly, then this code should work (not tested):

// define variables
var i,j,nRows,values,value,allowContinue,fieldname;

// collect values from document fields
nRows=viewScope.rows;
values=[];
for (i=0;i<nRows;i++) {
    values.push(document1.getItemValueString("ObjectiveDetails"+(i+1).toFixed(0)));
}

// fill empty values
for (i=0;i<nRows-1;i++) {
    if (values[i]) continue;
    allowContinue=false;
    for (j=i+1;j<nRows;j++) {
        if (value=values[j]) {
            values[i]=value;
            values[j]="";
            allowContinue=true;
            break;
        }
    }
    if (!allowContinue) break;
}

// write back to document and remove empty fields on the end
for (i=0;i<nRows;i++) {
    fieldname="ObjectiveDetails"+(i+1).toFixed(0);
    if (value=values[i]) document1.replaceItemValue(fieldname,value);
    else document1.removeItem(fieldname);
}
xpages-noob
  • 1,569
  • 1
  • 10
  • 37
2

This should be your core algorithm:

var writeIndex = 0;
for (var readIndex = 1; readIndex <= viewScope.rows; readIndex++) {
    var value = document1.getItemValueString("ObjectiveDetails" + readIndex);
    if (value) {
        writeIndex++;
        if (readIndex !== writeIndex) {
            document1.removeItem("ObjectiveDetails" + readIndex);
            document1.replaceItemValue("ObjectiveDetails" + writeIndex, value);
        }
    } else {
        document1.removeItem("ObjectiveDetails" + readIndex);
    }
}
viewScope.rows = writeIndex;

The code

  • deletes all empty fields,
  • renames fields to ObjectiveDetails1, ObjectiveDetails2, ObjectiveDetails3,... and
  • writes the resulting number of rows back to viewScope variable "rows".
Knut Herrmann
  • 30,880
  • 4
  • 31
  • 67
  • Knut thanks for this, xpages-noob also for your solution! I've modified Knuts code slightly to achieve some other things that I wanted to, but as you mentioned Knut, the core stuff was there to enable me to achieve what I wanted. One thing I've noticed... I do a full submit on a button running this code, and when it reloads, it still shows the deleted fields, however when I open the same document in a new tab or window, it correctly shows without the deleted fields. Any idea's? Thanks again for all contributions guys! – Chris Richards Jul 04 '17 at 14:18
  • That's what I'm trying - Its because in my beforePageLoad I run some code to build an array of fields from the backend document that display the correct fields (stored as viewScope variables). The rows viewScope is correctly showing 4 for example, however the fields viewScope variable still shows 7 elements (8 fields) Will update my question with beforePageLoad code – Chris Richards Jul 04 '17 at 15:56
  • IMO a full refresh does not suffice in that case. You will have to reload the full page in order for the beforePageLoad event to be executed again. You can test this by adding `context.reloadPage();` to the end of the code in your submit button. – xpages-noob Jul 04 '17 at 17:36
  • xpages-noob you are correct! I found the following blog post by Paul earlier this morning which says a full refresh only re-uses the component tree so to use context.reloadPage(); Thanks once again! (http://www.intec.co.uk/viewscope-full-refresh-reloadpage/) – Chris Richards Jul 05 '17 at 09:09