Page 1 of 1

onChange event executing twice

Posted: Tue May 29, 2018 2:50 am
by dan.v
Hey you fine folks of the internet.

I'm working on a little script and i can't seem to figure this one out:

Attached is a GUI script I've made and when executing everything works fine except for the fact that the two onChange events (compositions size dropdown and frame rate dropdown) are executing twice after setting the defaults. It's not braking my code or anything but my OCD just cant leave it as it is.

var compPresets = {  
        "240p": [426, 240],  
        "360p": [640, 360],  
        "480p": [854, 480],
        "720p": [1280, 720],
        "1080p": [1920, 1080],
        "1440p": [2560, 1440],
        "2160p": [3840, 2160],
        "2880p": [5120, 2880],
        "4320p": [7680, 4320],
        "Custom": [[],[]],  //if adding presets make sure this is the last one
var aspectPresets = {  
        "Square Pixels": 1,  
        "D1/DV NTSC (0.91)": 0.90909090909091,  
        "D1/DV NTSC Widescreen (1.21)": 1.21212121212121,
        "D1/DV Pal (1.09)": 1.09401709401709,
        "D1/DV Pal Widescreen (1.46)": 1.45868945868946,
        "HDV 1080/DVCPRO HD 720 (1.33)": 1.33333333333333,
        "DVCPRO HD 1080 (1.5)": 1.5,
        "Anamorphic 2:1 (2)": 2,
var ratePresets = {  
        "8": 8,  
        "12": 12,  
        "15": 15,
        "23.976": 23.976,
        "24": 24,
        "25": 25,
        "29.97": 29.97,
        "30": 30,
        "50": 50,
        "59.94": 59.94,
        "60": 60,
        "120": 120,
        "Custom": null, //if adding presets make sure this is the last one

var myPalette = buildUI(this);

if(myPalette != null && myPalette instanceof Window){;

function buildUI(thisObject){

    if(thisObject instanceof Panel){
        var UI = thisObject;
        var UI = new Window ("palette", scriptName, undefined, {resizeable:true});

    if (UI != null){
        var res = 
        "group {orientation: 'column', alignment: ['fill','fill'], alignChildren: ['left','top'],\
            buttonsGrp: Group{orientation: 'row', alignment: ['fill','top'],alignChildren: ['left','top'],\
                selectionBTN: Button {text:'Load Selection'},\
                importBTN: Button {text:'Import Files'},\
                clearBTN: Button {text:'Clear Selection', alignment: ['right','top']},\
            listGrp: Group {alignment: ['fill','fill'], alignChildren: ['fill','fill'],\
                loadList: ListBox{},\
            compSettings: Group{orientation: 'column', alignment: ['fill','Bottom'], alignChildren: ['fill','Bottom'],\
                dimentionPanel: Panel{text:'Composition Size', orientation: 'column', alignChildren: ['left','Bottom'],\
                    presetGrp: Group {orientation: 'row', alignment: ['left','Bottom'], alignChildren: ['left','Bottom'],\
                        presetText: StaticText {text:'Preset:', alignment: ['left','center']},\
                        presetItems: DropDownList{},\
                    customGrp: Group {orientation: 'row', alignment: ['left','Bottom'], alignChildren: ['left','Bottom'],\
                        widthText: StaticText {text:'Width:', alignment: ['left','center']},\
                        widthEdit: EditText {text:'50',characters:5},\
                        widthPxText: StaticText {text:'px', alignment: ['left','center']},\
                        heightText: StaticText {text:'Height:', alignment: ['left','center']},\
                        heightEdit: EditText {text:'50',characters:5},\
                        heightPxText: StaticText {text:'px', alignment: ['left','center']},\
                settingsPanel: Panel{text:'Composition Settings', orientation: 'column', alignChildren: ['left','Bottom'],\
                    ratioGrp: Group {orientation: 'row', alignment: ['left','Bottom'], alignChildren: ['left','Bottom'],\
                        ratioText: StaticText {text:'Pixel Aspect Ratio:', alignment: ['left','center']},\
                        ratioItems: DropDownList{},\
                    rateGrp: Group {orientation: 'row', alignment: ['left','Bottom'], alignChildren: ['left','Bottom'],\
                        rateText: StaticText {text:'Frame Rate:', alignment: ['left','center']},\
                        rateItems: DropDownList{},\
                        rateEdit: EditText {characters:3, alignment: ['left','center']},\
                    durationGrp: Group {orientation: 'row', alignment: ['left','Bottom'], alignChildren: ['left','Bottom'],\
                        durationText: StaticText {text:'Composition Duration:', alignment: ['left','center']},\
                        durationEdit: EditText {characters:6, alignment: ['left','center']},\
                        timeScale: DropDownList{properties:{items:['Frames','Seconds','Minutes','Hours']}},\
            renameCheck: Checkbox {text:'Rename Layers'},\
        UI.grp = UI.add(res);
        // Populate Composition Presets
        var compKeys = getObjectKeys(compPresets);
        for (i=0; i<compKeys.length; i++){
            UI.grp.compSettings.dimentionPanel.presetGrp.presetItems.add("item", compKeys[i]);
        // Populate Aspect Ratio Presets
        var ratioKeys = getObjectKeys(aspectPresets);
        for (i=0; i<ratioKeys.length; i++){
            UI.grp.compSettings.settingsPanel.ratioGrp.ratioItems.add("item", ratioKeys[i]);
        // Populate Frame Rate Presets
        var rateKeys = getObjectKeys(ratePresets);
        for (i=0; i<rateKeys.length; i++){
            UI.grp.compSettings.settingsPanel.rateGrp.rateItems.add("item", rateKeys[i]);
        // Set Composition Presets onChange event
        UI.grp.compSettings.dimentionPanel.presetGrp.presetItems.onChange = function(){
            var cpSelection=this.selection.index; 
            UI.grp.compSettings.dimentionPanel.customGrp.widthEdit.text = compPresets[compKeys[cpSelection]][0];
            UI.grp.compSettings.dimentionPanel.customGrp.heightEdit.text = compPresets[compKeys[cpSelection]][1];
            if(cpSelection == compKeys.length-1){
                UI.grp.compSettings.dimentionPanel.customGrp.enabled = true;
                UI.grp.compSettings.dimentionPanel.customGrp.enabled = false;
        // Set Frame Rate Presets onChange event
        UI.grp.compSettings.settingsPanel.rateGrp.rateItems.onChange = function(){
            var rpSelection=this.selection.index; 
            UI.grp.compSettings.settingsPanel.rateGrp.rateEdit.text = ratePresets[rateKeys[rpSelection]];

            if(rpSelection == rateKeys.length-1){
                UI.grp.compSettings.settingsPanel.rateGrp.rateEdit.enabled = true;
                UI.grp.compSettings.settingsPanel.rateGrp.rateEdit.enabled = false;
        UI.grp.compSettings.dimentionPanel.presetGrp.presetItems.selection = 4;
        UI.grp.compSettings.settingsPanel.ratioGrp.ratioItems.selection = 0;
        UI.grp.compSettings.settingsPanel.rateGrp.rateItems.selection = 5;
        UI.grp.compSettings.settingsPanel.durationGrp.timeScale.selection = 0; 
        //Setup Panel Size
        UI.grp.minimumSize = UI.grp.size;
        //Setup Panel Resizing
        UI.onResizing = UI.onResize = function(){this.layout.resize();}
    } //end if (UI != null)

    return UI;
} //end function buildUI()

function getObjectKeys(object) {  
        var keys = [];  
        for (var property in object) {  
            if (!object.hasOwnProperty(property)) continue;  
        return keys;  

Any idea why this happens and how to solve this?
Also it's my first script so if I made any cardinal sin let me know...

Thanks in advance, Dan

Re: onChange event executing twice

Posted: Tue May 29, 2018 7:23 am
by wysee
I tried your script, 
Move your defaults block before your onChange function and that will fix it.
Also, you should wrap your entire Script inside a function block to keep your variables local to your script, and not global.


Re: onChange event executing twice

Posted: Wed May 30, 2018 1:39 am
by dan.v
Hey Ben, thank you so much and shame on me for not figuring this one out.
Also thanks for the tip, funny, i'm following several tutorials and none mentioned wrapping the script. 
Probably another noob question: but do you wrap all your scripts or only gui scripts?


Re: onChange event executing twice

Posted: Sat Jun 02, 2018 4:13 pm
by zlovatt
dan.v wrote:
[...] do you wrap all your scripts or only gui scripts?


All of them. Otherwise any other tool can manipulate or execute your code, either deliberately or not. 
For example: you never declare what scriptName is. So my unwrapped script could declare var scriptName = "hi";, and now your panel when you run it will be titled "hi".
If you simply wrap your script in a function, then there's zero risk of cross-contamination.