13 Replies Latest reply on Aug 18, 2016 9:38 AM by xbytor2

    Problem file browsing on OSX - How to use a filter function?

    Heimdaal Level 1

      I'm working with file browsing atm using the File objects in JSX and the openDlg -method and quite frankly, this is driving me insane.

      Did some crazy person decide that it was a good idea to have the filter-flag on the openDlg -method totally different for Win and OSX? On windows you use a string for the filtering, on OSX it want's a function!

       

      I've checked the documentation and also searched this forum and I can't even find an example of how to set this up so that it works for both Windows and OSX?

       

      Ok so I've found the syntax, but it still doesn't make sense.

      fileMask = function(file){file.name.match(/\.psd$/i) ? true:false;}
      


      Here we have the psd-extension hardcoded into the regular extension. But what if we want it to be a variable? And what if t he file doesn't exist yet.

       

      Basically what I want is for the user to:
      Browse to a folder

      set a file name

      save.

      The extension type should be locked!

       

       

      Compared to the windows way of doing things, the OSX way of using a filter function is nonsensical, overly complex and downright annoying!

       

      EDIT: I also discovered that you can't write a file name on OSX unless the file already exists. Come on! Is this the wrong dialog type or something???

        • 1. Re: Problem file browsing on OSX - How to use a filter function?
          matias.kiviniemi Level 3

          Here's my script for prompting a file which handles the Win/Mac differences

           

          function isWindows() {
            return app.systemInformation.indexOf("Operating System: Windows") >= 0
          }
          function isMac() {
            return app.systemInformation.indexOf("Operating System: Mac") >= 0
          }
          function promptFile(filter_extension) {
            var filter = null
            if (isMac()) {
                 if (filter_extension) {
                      var filter_regex = new RegExp("[^\.]*\."+filter_extension+"$")
                      filter = function (file_entry) {
                           return filter_regex.test(file_entry.name)
                      }
                 } else {
                      filter = function () { return true }
                 }
            } else if (isWindows()) {
                 if (filter_extension) {
                      filter = filter_extension.charAt(0).toUpperCase() + filter_extension.slice(1)+"-files:*."+filter_extension
                 } else {
                      filter = "All files:*.*"
                 }
            } else {
                 filter = null
            }
            var f = File.openDialog("Select your file", filter, false)
            if (f) {
                 return f.fsName.replace(/\\/g, "/") // sanitize to forward slash
            }
          }
          }
          
          1 person found this helpful
          • 2. Re: Problem file browsing on OSX - How to use a filter function?
            xbytor2 Level 4

            In xtools, I do it like this:

            Stdlib.createFileSelect = function(str) {
              if (isWindows()) {
                return str;
              }
              if (!str.constructor == String) {
                return str;
              }
              var exts = [];
              var rex = /\*\.(\*|[\w]+)(.*)/;
              var m;
              while (m = rex.exec(str)) {
                exts.push(m[1].toLowerCase());
                str = m[2];
              }
              function macSelect(f) {
                var name = decodeURI(f.absoluteURI).toLowerCase();
                var _exts = macSelect.exts;
                // alert(name);
                while (f.alias) {
                  try {
                    f = f.resolve();
                  } catch (e) {
                    f = null;
                  }
                  if (f == null) {
                    return false;
                  }
                }
                if (f instanceof Folder) {
                  return true;
                }
                var fext = f.strf("%e").toLowerCase();
                for (var i = 0; i < _exts.length; i++) {
                  var ext = _exts[i];
                  if (ext == '*') {
                    return true;
                  }
                  if (fext == ext) {
                    return true;        
                  }
                  // if (name.match(RegExp("\\." + ext + "$", "i")) != null) {
                  //   return true;
                  // }
                }
                return false;
              }
              macSelect.exts = exts;
              return macSelect;
            };
            

             

             

            This way, you can use a Windows file filter and it converts it to a Mac file filter. I've used this for years in multiple projects.

            1 person found this helpful
            • 3. Re: Problem file browsing on OSX - How to use a filter function?
              Heimdaal Level 1

              Thanks.

              That looks overly complicated for something that should be so simple.

              I did try your code though Matias and it works. But how can I change it to work with old paths?

               

              This is my current code:

              function browser2(objType, ext, fullPath){
              
                  if (objType == "file"){
                      var path = new File(fullPath);
                      if(File.fs != "Windows") ext = function(){return true}; // OSX wai u do diz?
                      var dialog = path.openDlg(dialogMessage, ext);
                      while (dialog.alias){
                          dialog = dialog.resolve().saveDlg(dialogMessage);
                      }
                  }else if (objType == "folder"){
                      var path = new Folder(fullPath);
                      var dialog = path.selectDlg(dialogMessage);
                      while (dialog.alias){
                          dialog = dialog.resolve.selectDlg(dialogMessage);
                      }
                  }
              }
              

               

              On Windows this works exactly as it should. I tell the function if I want to browse for a file or a folder. I can also provide an old path and the dialog will start browsing from that point. The openDlg and selectDlg -methods respects the path to the object.


              On OSX the dialog ALWAYS browser for folders ONLY and always from the last browsing point made on the system. The path to the object doesn't even seem to matter for the openDlg and selectDlg methods - Why?

              • 4. Re: Problem file browsing on OSX - How to use a filter function?
                Heimdaal Level 1

                I added an extra parameter to promptFile() - sending in the old path to the file (oldPath variable), then

                var path = new File(oldPath);

                var f = path.openDialog("Select your file", filter)

                 

                 

                openDialog doesn't work so I changed it to openDlg. The old path is opened up and the filter is correct (Windows) but I am not able to actually save a new file. Makes sense since it's the openDlg and not the saveDlg.

                 

                But when using saveDlg the starting file name is the filter! Also if I specify a name I get an error message saying: "myName. The file name is not valid" - this is regardless of how I write it!
                Also tried saveDialog() - which doesn't allow me to specify a path in advance - and I get exactly the same kind of error. The file name is not valid.

                • 5. Re: Problem file browsing on OSX - How to use a filter function?
                  matias.kiviniemi Level 3

                  In Mac the filter is a function that gets called for every file in a folder and you are supposed to return true/false depending if you are interested of it. That's why if it's null (basically assuming false for every file), you just get the folders. The Win version is simpler (and less powerfull) just specifying a set of file extensions as a specially formatted string.

                   

                  My script is intended that you can just give the extension you are looking for or null for all files.

                  • 6. Re: Problem file browsing on OSX - How to use a filter function?
                    Heimdaal Level 1

                    I see.

                    Well there seems to be something wrong: I modified your script so that I send in an extra parameter with the old path, and then I use saveDialog. Filter works, but the starting location when browsing is incorrect. Additionally I am unable to actually save the file (error says the file name is not valid!).

                     

                    // Doesn't work at all. Opens up browsing starting from the user's desktop. Has the filter as a name.
                    var path = new File(oldPath);
                    var f = path.saveDialog("Select your file", filter, false);
                    
                    
                    // Doesn't work at all. Opens up browsing starting from the user's desktop. Has the filter as a name.
                    var path = new File(oldPath);
                    var f = path.saveDlg("Select your file", filter, false);
                    
                    
                    // Opens up the correct file path - but doesn't allow saving
                    var path = new File(oldPath);
                    var f = path.openDlg("Select your file", filter, false);
                    
                    
                    // Doesn't open up dialog
                    var path = new File(oldPath);
                    var f = path.openDialog("Select your file", filter, false);
                    
                    • 7. Re: Problem file browsing on OSX - How to use a filter function?
                      Heimdaal Level 1

                      Current code - Problems mentioned in the comments

                      function isWindows(){
                          return app.systemInformation.indexOf("Operating System: Windows") >= 0
                      }
                      function isMac(){
                          return app.systemInformation.indexOf("Operating System: Mac") >= 0
                      }
                      
                      
                      function promptFile(filter_extension, oldPath){
                          var filter = null
                          if (isMac()){
                              if (filter_extension){
                                  var filter_regex = new RegExp("[^\.]*\."+filter_extension+"$")
                                  filter = function (oldPath){
                                      return filter_regex.test(oldPath.name)
                                  }
                              }else{
                                  filter = function(){ return true }
                              }
                          }else if (isWindows()){
                              if (filter_extension){
                                  filter = filter_extension.charAt(0).toUpperCase() + filter_extension.slice(1)+"-files:*."+filter_extension
                              }else{
                                  filter = "All files:*.*"
                              }
                          }else{
                              filter = null
                          }
                      
                      
                          // alert("oldPath is: " + oldPath);
                      
                      
                          // Starts browsing where it is supposed to start browsing (oldPath) and allows me to overwrite existing files.
                          // However, when starting the dialog the file name is always oldFileName.atlas.*.atlas
                          // Also, when trying to save a new file I get an error saying that the file name is invalid!
                          var path = new File(oldPath);
                          var f = path.saveDlg("Select your file", filter, false);
                      
                      
                          if (f){
                              return f.fsName.replace(/\\/g, "/") // sanitize to forward slash
                          }
                      }
                      
                      • 8. Re: Problem file browsing on OSX - How to use a filter function?
                        matias.kiviniemi Level 3

                        To be honest, I've never used saveDlg so not sure if that changes something. But at least one problem, you had replaced "file_entry" with "oldPath" in the filter function. What below means is you create a dynamic function that get's called with every file in the dialog window and it tests if the filename is suitable (has proper prefix). Variable file_entry is the parameter (of type File) of the function, using oldPath might confuse it with the higher level variable.

                         

                        filter = function (file_entry){  
                          return filter_regex.test(file_entry.name)  
                        }  
                        

                         

                        Also make sure you call the function with extension only, i.e. "atlas", not ".atlas" or "*.atlas". And try debugging with ESTK, very easy to make a small text parsing error

                        1 person found this helpful
                        • 9. Re: Problem file browsing on OSX - How to use a filter function?
                          matias.kiviniemi Level 3

                          I checked the docs (javascript tools guide) and saveDlg takes a filter only in Windows, which allows you to set type like *.*, *.atlas. So you can try leaving it out.

                          1 person found this helpful
                          • 10. Re: Problem file browsing on OSX - How to use a filter function?
                            Heimdaal Level 1

                            Thanks.

                            I changed back the file_entry variable and also provided promptFile() with a proper extension.
                            I had given the function an incorrect string - setting it to "atlas" made things working.

                             

                            File browsing works on Windows but I get some other weird problem on OSX now:

                            Every single folder is greyed out.

                             

                            function isWindows(){
                                return app.systemInformation.indexOf("Operating System: Windows") >= 0
                            }
                            
                            
                            function isMac(){
                                return app.systemInformation.indexOf("Operating System: Mac") >= 0
                            }
                            
                            
                            function promptFile(dialogMessage, extFilter, oldPath){
                                var filter = null
                                if (isMac()){
                                    if (extFilter){
                                        var filter_regex = new RegExp("[^\.]*\."+extFilter+"$")
                                        filter = function (fileEntry){
                                            return filter_regex.test(fileEntry.name)
                                        }
                                    }else{
                                        filter = function(){ return true }
                                    }
                                }else if (isWindows()){
                                    if (extFilter){
                                        filter = extFilter.charAt(0).toUpperCase() + extFilter.slice(1)+"-files:*."+extFilter
                                    }else{
                                        filter = "All files:*.*"
                                    }
                                }else{
                                    filter = null
                                }
                            
                            
                                var path = new File(oldPath);
                                var f = path.saveDlg(dialogMessage, filter, false);
                            
                            
                                if (f){
                                    return f.fsName.replace(/\\/g, "/")
                                }
                            }
                            
                            
                            // Start browsing:
                            promptFile(dialogMessage, extension, fullPath)
                            

                             

                            The weird thing is that even though the documentation says that the second parameter to saveDlg() is only used by windows, it still appears as if the filter function is working. Sure, ALL folders are greyed out and I am unable to browse, but under "Save As" I have proper extension specified!

                             

                            Another clue: I get the same problem on OSX with greyed out folders when using openDlg()

                            • 11. Re: Problem file browsing on OSX - How to use a filter function?
                              matias.kiviniemi Level 3

                              Heh, this is getting confusing

                               

                              There seems to be _SEVERAL_ versions of the save dialogs

                              • file_entry.saveDlg(): Content of file_entry is the default value but not sure if it's locked to it
                              • File.saveDialog(): same as file_entry.saveDlg, but no preselect value. Maybe it's not locked to original dir
                              • folder_entry.saveDlg(): seems identical to file_entry.saveDlg, not sure if there is a difference.
                              • Folder.selectDialog: seems most general purpose, "just pick a file"

                               

                              You probably have to just do some trial and error to pick the best one, what rules each has. As far as I see Mac has no option to "create a new file, but only this extension". Extension filter only seems to apply to opening existing and Win (although even there it's just hiding, you can actually set different extension by typing it).

                               

                              Confusing part is that the "all folders grayed" would implicate it actually wants the filter even though docs say it does not. I.e. youd have to make a filter function that accepts either folders or files with right extension like below (not tested)

                               

                              filter = function (fileSystemEntry){ 

                                if (fileSystemEntry instanceof Folder) {

                                return true

                                } else {

                                return filter_regex.test(fileSystemEntry.name) 

                                }

                              }

                              • 12. Re: Problem file browsing on OSX - How to use a filter function?
                                Heimdaal Level 1

                                I'll make a separate thread about the grey-out problem as the original question has been answered already. I marked your response as the correct answer Matias.

                                • 13. Re: Problem file browsing on OSX - How to use a filter function?
                                  xbytor2 Level 4

                                  Here's how I do it in xtools, You can replace f.strf("%e") with whatever function you use to extract a file extension.

                                  This expects a Windows-style file selection string and returns that or a filter function if it's on a Mac.

                                   

                                  isWindows = function() {

                                    return $.os.match(/windows/i);

                                  };

                                  Stdlib.createFileSelect = function(str) {
                                    if (isWindows()) {
                                      return str;
                                    }

                                    if (!str.constructor == String) {
                                      return str;
                                    }

                                    var exts = [];
                                    var rex = /\*\.(\*|[\w]+)(.*)/;
                                    var m;
                                    while (m = rex.exec(str)) {
                                      exts.push(m[1].toLowerCase());
                                      str = m[2];
                                    }

                                    function macSelect(f) {
                                      var name = decodeURI(f.absoluteURI).toLowerCase();
                                      var _exts = macSelect.exts;

                                      // alert(name);

                                      while (f.alias) {
                                        try {
                                          f = f.resolve();
                                        } catch (e) {
                                          f = null;
                                        }

                                        if (f == null) {
                                          return false;
                                        }
                                      }

                                      if (f instanceof Folder) {
                                        return true;
                                      }
                                      var fext = f.strf("%e").toLowerCase();

                                      for (var i = 0; i < _exts.length; i++) {
                                        var ext = _exts[i];
                                        if (ext == '*') {
                                          return true;
                                        }
                                        if (fext == ext) {
                                          return true;       
                                        }
                                    }
                                      return false;
                                    }

                                    macSelect.exts = exts;
                                    return macSelect;
                                  };