Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
0

ScriptUI: delete listbox and create a new one in its place

Mentor ,
Feb 15, 2020 Feb 15, 2020

Good day!
I have a script that does some work based on data from csv files. When working with a script, a user can upload several files sequentially (i.e., after finishing working with one file, I need to make it so that the user can load another without closing the script window). The csv files have a different structure and a different number of fields (this is controlled by the user) - it seemed to me convenient to show them using a listbox with headers.

 

Before the user specifies the file, I open the form with an empty listbox object (just to reserve a place for it in the form):

2020-02-15_23-41-00.png

After reading and processing the csv file, I create a new listbox object using the buildList() function. To do this, I delete the previously created testList object from the form, then load a new one in its place. And at this moment i have a problem with ScriptUI:

2020-02-15_23-18-58.png

If I do not delete the object, then the listbox will display normally (but old instances will be preserved):

2020-02-15_23-18-39.png

It is clear that i can rewrite the function so that for each csv file a new instance of the window is loaded in which a listbox with the necessary parameters will be immediately generated, but in my case this is inconvenient for the user.

 

I trying to understand - is this a bug of ScriptUI or am I doing something wrong?

 

(the example is simplified, just to demonstrate the problem)

 

 

#target photoshop

var parsedCSV = [["TestField1", "TestField2", "060", "070", "080", "090"], ["TestField3", "TestField4", "145"], ["TestField5", "TestField6", "361"]]

    var w = new Window("dialog"),
    oldList = w.add('listbox', [0,0,520,200]),
    bn = w.add("button", undefined, "test")
    
    bn.onClick = function () {
        w.remove (oldList) // problem here, i'm trying also w.remove (w.children[0])
        buildList(parsedCSV)
    }

    w.show ()

function buildList (list) {
    var columns=0, 
    wordLen={}

    for (var i=0; i<list.length; i++){
        if (list[i].length>columns) columns = list[i].length
        for (var n=0; n<list[i].length; n++){
            if (wordLen[n]=undefined) {
                wordLen[n] = list[i][n].length
            } else {
                if (list[i][n].length > wordLen[n]) wordLen[n] =list[i][n].length 
            }
        }
    }

    var props = { numberOfColumns: columns, showHeaders: true, columnTitles: [], columnWidths: [] }

    for (var i=0; i<columns; i++){
        props.columnTitles.push(String(i+1))
        props.columnWidths.push(wordLen[i]*12)
    }

    newList = w.add("listbox", [0, 0, 520, 200], undefined, props)
    
    for (var i = 0; i < list.length; i++) {
        var cur = list[i]
        newList.add("item", cur[0])
        for (var n = 1; n < cur.length; n++) {
            newList.items[i].subItems[n - 1].text = cur[n];
        }
    }
    
    w.layout.layout(true)
}

 

 

 

TOPICS
Actions and scripting
2.8K
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

People's Champ , Feb 15, 2020 Feb 15, 2020
var parsedCSV = [["TestField1", "TestField2", "060", "070", "080", "090"], ["TestField3", "TestField4", "145"], ["TestField5", "TestField6", "361"]]

    var w = new Window("dialog")

    w.p1 = w.add("group");
    w.p1.margins = 0;

    w.p2 = w.p1.add("group");
    w.p2.margins = 0;
    
    oldList = w.p2.add('listbox', [0,0,520,200], [1,2,3]);

    bn = w.add("button", undefined, "test")

    bn.onClick = function () {
        w.p1.remove(w.p2);
        buildList(parsedCSV)
    }

    w.show
...
Translate
Adobe
LEGEND ,
Feb 15, 2020 Feb 15, 2020

Change this example (where innitially there's one set replaced by other when clicking button) to your needs:

 

lst = (win = new Window('dialog')).add('dropdownlist', [0, 0, 100, 20], [])
lst.add('item', [1, 2, 3]), btn = win.add('button', [0, 0, 60, 21], 'Replace')
btn.onClick = function() {lst.removeAll(), lst.add('item', [4, 5])} win.show()
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Mentor ,
Feb 15, 2020 Feb 15, 2020

The problem is that the set of headers in the listbox can be changed ONLY when it is created (i.e. numberOfColumns, showHeaders, columnTitles is a creation properties). It’s not enough for me to simply clear list, I need to recreate the object itself with a different set of fields

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Feb 15, 2020 Feb 15, 2020

Change appropriate lines of your script to these codes:

var w = new Window("dialog"), grp = w.add('group')
oldList = grp.add('listbox', [0,0,520,200])

 

grp.remove (grp.children[0]) // problem here, i'm trying also w.remove (w.children[0])

 

newList = grp.add("listbox", [0, 0, 520, 200], undefined, props)

 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Mentor ,
Feb 15, 2020 Feb 15, 2020

Same result. Any other objects are deleted and created in this way normally, the problem is only in the listbox with headers.

 

It seems i have found a solution: if put the listbox in another object (group or panel) and delete not listbox, but his parent (with creating a new one in the function), then everything works fine:

 

 

#target photoshop

var parsedCSV = [["TestField1", "TestField2", "060", "070", "080", "090"], ["TestField3", "TestField4", "145"], ["TestField5", "TestField6", "361"]]

    var w = new Window("dialog"),
    bn = w.add("button", undefined, "test"),
    grp = w.add('group'),
    oldList = grp.add('listbox', [0,0,520,200])
   
    
    bn.onClick = function () {
        w.remove (w.children[1]) // remove parent
        buildList(parsedCSV)
    }

    w.show ()

function buildList (list) {
    var columns=0, 
    wordLen={}

    for (var i=0; i<list.length; i++){
        if (list[i].length>columns) columns = list[i].length
        for (var n=0; n<list[i].length; n++){
            if (wordLen[n]=undefined) {
                wordLen[n] = list[i][n].length
            } else {
                if (list[i][n].length > wordLen[n]) wordLen[n] =list[i][n].length 
            }
        }
    }

    var props = { numberOfColumns: columns, showHeaders: true, columnTitles: [], columnWidths: [] }

    for (var i=0; i<columns; i++){
        props.columnTitles.push(String(i+1))
        props.columnWidths.push(wordLen[i]*12)
    }
    
    var grp = w.add('group'),
    newList = grp.add("listbox", [0, 0, 520, 200], undefined, props)
    
    for (var i = 0; i < list.length; i++) {
        var cur = list[i]
        newList.add("item", cur[0])
        for (var n = 1; n < cur.length; n++) {
            newList.items[i].subItems[n - 1].text = cur[n];
        }
    }
    
    w.layout.layout(true)
}

 

 

 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Feb 15, 2020 Feb 15, 2020

Try following codes (in your first script with my previous changes).

 

Under your first parsedCSV array paste:

 

var parsedCSV2 = [["TestField2", "070", "080", "090"], ["TestField4", "TestField5", "155"], ["TestField6", "TestField7", "371"]]

 


while appropriate line in bn.onClick function change to:

 

buildList(!$.getenv('csv') ? ($.setenv('csv', 1), parsedCSV) : ($.setenv('csv', ''), parsedCSV2))

 

 

 

 

btw the groups you say you found you can put the list to I already posted as solution to a problem, didn't you notice it? 🙂

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Mentor ,
Feb 15, 2020 Feb 15, 2020

Checked. Got the same result.

 

The problem is that the number of headers can vary. Please note - first I create an empty listbox with no headers (just so that the user sees the place of the object on the form). Only after parsing csv (receiving an array in this example) I determine how many headers are needed and create a listbox with this headers for a specific file - that’s why I recreate the object, and not just changing the dataset in it.

 

Believe me, I carefully read your messages and try all the proposed options 🙂 You did not offer to remove the parent itself, but proposed to remove the object from his parent - unfortunately, this does not work as expected in that case (but works fine with any other scriptUI objects in 99% of cases). Try to run my first example and you will understand what the problem is. When only reading code without running it, it is not obvious.

 

Anyway, thanks. I always read your comments with interest.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Feb 15, 2020 Feb 15, 2020

I read twice what you wrote now and I'm sure I know what you asked for. So to make it clear I'm posting your first script of first set of my updates and then of those from another post. Run it and tell me if that is not what you wanted. As you see depending of number of cells in array the number of headers varies, so isn't that okey?

btw I tried the script originally in CS6, where it works well. I guess that must be same Ps on your side because later I tried it in CC2019 and CC2020 and after clicking Test button nothing happened.

Anyway if that's CS6 try my script and see it works the way I understood it should.

 

Ps. the environmental variables I used only because CSV data is put in variables not in outer file, the content of may be changed.

 

 

var parsedCSV = [["TestField1", "TestField2", "060", "070", "080", "090"], ["TestField3", "TestField4", "145"], ["TestField5", "TestField6", "361"]]
var parsedCSV2 = [["TestField2", "070", "080", "090"], ["TestField4", "TestField5", "155"], ["TestField6", "TestField7", "371"]]

var w = new Window("dialog"), grp = w.add('group')
oldList = grp.add('listbox', [0,0,520,200])
bn = w.add("button", undefined, "test")
    
bn.onClick = function () {
	grp.remove (grp.children[0]) // problem here, i'm trying also w.remove (w.children[0])
	buildList(!$.getenv('csv') ? ($.setenv('csv', 1), parsedCSV) : ($.setenv('csv', ''), parsedCSV2))
}

w.show()

function buildList (list) {
	var columns=0, 
	wordLen={}

    for (var i=0; i<list.length; i++){
        if (list[i].length>columns) columns = list[i].length
        for (var n=0; n<list[i].length; n++){
            if (wordLen[n]=undefined) {
                wordLen[n] = list[i][n].length
            } else {
                if (list[i][n].length > wordLen[n]) wordLen[n] =list[i][n].length 
            }
        }
    }

	var props = { numberOfColumns: columns, showHeaders: true, columnTitles: [], columnWidths: [] }

	for (var i=0; i<columns; i++){
		props.columnTitles.push(String(i+1))
		props.columnWidths.push(wordLen[i]*12)
	}

	newList = grp.add("listbox", [0, 0, 520, 200], undefined, props)
    
    for (var i = 0; i < list.length; i++) {
        var cur = list[i]
        newList.add("item", cur[0])
        for (var n = 1; n < cur.length; n++) {
            newList.items[i].subItems[n - 1].text = cur[n];
        }
    }
    
	w.layout.layout(true)
}

 

 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
People's Champ ,
Feb 15, 2020 Feb 15, 2020
Remark.

Interestingly, when did they manage to fix the multi-columned listboxes?
Nothing works in CC2018.

But there are problems in the CC2020 if you are trying to set a user font for such a listboxes.

In short, complete garbage.
 
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Feb 15, 2020 Feb 15, 2020

They encourage to use HTML and Javascript Extensions instead of ScriptUI.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
People's Champ ,
Feb 15, 2020 Feb 15, 2020

Morons.

 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
People's Champ ,
Feb 15, 2020 Feb 15, 2020
var parsedCSV = [["TestField1", "TestField2", "060", "070", "080", "090"], ["TestField3", "TestField4", "145"], ["TestField5", "TestField6", "361"]]

    var w = new Window("dialog")

    w.p1 = w.add("group");
    w.p1.margins = 0;

    w.p2 = w.p1.add("group");
    w.p2.margins = 0;
    
    oldList = w.p2.add('listbox', [0,0,520,200], [1,2,3]);

    bn = w.add("button", undefined, "test")

    bn.onClick = function () {
        w.p1.remove(w.p2);
        buildList(parsedCSV)
    }

    w.show ()

function buildList (list) {
    var columns=0, 
    wordLen={}

    for (var i=0; i<list.length; i++){
        if (list[i].length>columns) columns = list[i].length
        for (var n=0; n<list[i].length; n++){
            if (wordLen[n]=undefined) {
                wordLen[n] = list[i][n].length
            } else {
                if (list[i][n].length > wordLen[n]) wordLen[n] =list[i][n].length 
            }
        }
    }

    var props = { numberOfColumns: columns, showHeaders: true, columnTitles: [], columnWidths: [] }

    for (var i=0; i<columns; i++){
        props.columnTitles.push(String(i+1))
        props.columnWidths.push(wordLen[i]*12)
    }


    w.p2 = w.p1.add("group");

    newList = w.p2.add("listbox", [0, 0, 520, 200], undefined, props)
    
    for (var i = 0; i < list.length; i++) {
        var cur = list[i]
        newList.add("item", cur[0])
        for (var n = 1; n < cur.length; n++) {
            newList.items[i].subItems[n - 1].text = cur[n];
        }
    }
    
    w.layout.layout(true)
}
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Mentor ,
Feb 15, 2020 Feb 15, 2020
LATEST

Thanks. A few messages above i found some solution

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines