7 Replies Latest reply on Apr 6, 2017 12:54 AM by cmoke73

    Use a variable in multiple functions

    cmoke73 Level 1

      Hello!

      The headline tells the story:

       

      var myDoc = app.documents[0]; 
      var myPage = myDoc.pages[0]; 
      var allSelection = myDoc.selection;
      var mySelection = allSelection[0];
      var numbSelection = allSelection.length;
      
      funktion checkSelection () {
          for (var i=0; i < numbSelection; i++) {
      
              if(no selection){
              error message
              }
      
              else if (wrong selection) {
              error message
              }
      
              else if (no table) {
              error message
              }
      
              else{
                      createObjectStyle();    
                 
                      var myTables = allSelection[i].tables.everyItem();
      
                     clearOverrides();
                      tableStyles();
                      cellStyles();    }
          }
      }
      
      funktion clearOverrides(){
      … (using „myTables“)
      }
      
      funktion cellStyles(){
      … (using „myTables“)
      }
      
      funktion tableStyles(){
      … (using „myTables“)
      }
      
      funktion createObjectStyle(){
      … (not using "myTables)
      }
      

       

      Why is the variable "myTables" not recognized (is undefined) in the function "clearOverrides"?

        • 1. Re: Use a variable in multiple functions
          [Jongware] Most Valuable Participant

          This is called variable scope -- it determines the 'lifetime' and 'visibility' of a variable inside and outside of functions and bracketed parts such as "if", "for", and "while" blocks.

           

          Longer, technically minded stories: Understanding Global & Local Scope in Javascript - Stack Overflow  (possibly also Variable: local scope, global scope or is it the JavaScript engine? - Stack Overflow ).

           

          Short version, and most likely the cause of your problems: it's not just the "var". What if you run this script and the 'else' part that defines myTables never gets executed?

           

          You declared your other variables at the start of your script, just do the same with 'myTables', even if it's only as an empty array:

           

          var myTables = [];

          • 2. Re: Use a variable in multiple functions
            cmoke73 Level 1

            Hi Jongware. Thank you for answering that fast.

            What if you run this script and the 'else' part that defines myTables never gets executed?

             

            But I think the "else"-part has to be executed. There is no other way, isn´t it?

             

            funktion checkSelection():

            1.) verify wheather it is ANYTHING selected (doesn´t work- don´t know why: if (numbSelection < 1) )

            if there is:

            2.) is a Text-Frame selected?

            if there is also:

            3.) does it contain a table?

            if it does:

            4.) do something with it: create the var myTables and call the functions (myTables can not "get in" the functions)

             

            You declared your other variables at the start of your script, just do the same with 'myTables', even if it's only as an empty array:

            ==> "undefined, is not an object"

            Maybe it misses content for the var (myTables)?

            • 3. Re: Use a variable in multiple functions
              Trevorׅ Adobe Community Professional

              Hi Cmoke

               

              When you declare a variable in function x it will not be available to function y unless y is contained inside  function x

               

              function x(foo) {
                  function y() {
                      return foo;
                  }
                  return y();
              }
              x('foo'); // => foo
              

               

              or

              function x(foo) {
                  var Q;
                   y = function y() {
                      return Q;
                  };
                  Q = 5;
                  return y();
              }
              x('foo'); // => 5
              

               

              This is what local functions are about.

               

              What you need to do is pass the variables.

              The normal way to do that is to pass them explicitly, one can also pass them using the  arguments value but don't worry about that one for now.

              The key word you are looking for is "Scope"

               

              function f1(a, b, c, d, e) {
                  f2(a, b, c, d, e);
              }
              
              function f2(a, b, c, d, e) {
                  d *= 10;
                  e = 100;
                  $.writeln([a, b, c, d, e].join(' - f2\n') + ' - f2');
                  f3(arguments);
              
              }
              
              function f3() {
                  var n, c;
                  n = arguments[0].length;
                  for (c = 0; c < n; c++) {
                      $.writeln('arguments[0][' + c + ']: ' + arguments[0][c] + ' in function ' + arguments.callee.name + '  was called by function ' + arguments[0].callee.name);
                  }
              }
              
              f1(1, 2, 3, 4);
              
              • 4. Re: Use a variable in multiple functions
                Trevorׅ Adobe Community Professional

                I thought someone might have replied by the time I wrote mine, but I took the chance.

                • 5. Re: Use a variable in multiple functions
                  cmoke73 Level 1

                  Thanx Trevor.

                   

                  Now, after some tutorials (functions, parameters, return, and stuff):

                  I passed the variable with "return" instead parameters. Is that incorrect?

                   

                  var globalOne = "global Variable 1";
                  var globalTwo = "global Variable 2";
                  var globalThree = "global Variable 3";
                  
                  switch (confirm("Shall I continue?")) {
                      case false: alert("Wrong choice!");
                      break;
                      
                      case true: mainFunction();  $.writeln(localOne +"\r"  + localTwo +"\r"  + localThree);
                      break;
                      
                      default: alert("Do something!");
                      break;
                      
                      }
                  
                  function mainFunction(){
                      hiddenVar = "GotIt";
                      
                      functionOne();
                      functionTwo();
                      functionThree()
                      return hiddenVar;
                  }
                  
                  function functionOne(){
                      localOne = "local Variable 1 " + hiddenVar;
                      return localOne;
                      }
                  
                  function functionTwo(){
                       localTwo = "local Variable 2 " + hiddenVar;
                      return localTwo;
                      }
                  
                  function functionThree(){
                       localThree = "local Variable 3 " + hiddenVar;
                       return localThree;
                     }
                  

                   

                  It works. The construct is nearly the same like my real code but more simple.

                  There is something I do not understand: why it works like this but doesn´t, if I write (in line 18) var hiddenVar = "GotIt"; ???

                   

                  Now I look for the bug in my "real" code, because it does not work as it should...

                  • 6. Re: Use a variable in multiple functions
                    Trevorׅ Adobe Community Professional

                    In the code you posted line 18 is

                    hiddenVar = "GotIt"; and not var hiddenVar = "GotIt";

                    The var is the crucial difference without it the variable becomes a global and pollutes the entire workspace.

                    It is as about as unhidden as you can get. You could rename it publicVar or globalVar.

                    You need to get these scope issues sorted out.

                    See if this helps

                    function wrapper() {
                        var en = 'hello';
                        var fr = 'Bonjour';
                        de = 'Hallo';
                    
                        function f() {
                            var en = 'world';
                            de = 'Welt';
                            fr = 'Monde';
                            alert([en, fr, de].join('\n')); // => world Monde Welt
                        }
                    
                        alert([en, fr, de].join('\n')); // => hello Bonjour Hallo -- this call is made before function f has polluted our de and fr values
                        f();
                        alert([en, fr, de].join('\n')); // => hello Bonjour Hallo -- this call is made after function f has polluted our de and fr values
                        // en is still safe because of the var it is insulated from scope border crossings
                    }
                    wrapper();
                    alert(de); // => welt -- de polluted the entire welt no var at all
                    alert(en); // => crash en is Undefined -- this is what we want yes to crash no to pollution (no politics here)
                    

                     

                     

                    Regards

                    Trevor

                    • 7. Re: Use a variable in multiple functions
                      cmoke73 Level 1

                      Hi Trevor!

                      You´re pretty carefull avoiding any political jokes.

                       

                      I´m wondering why one don´t need return in this case to use the variable outside the function?

                       

                      Following a corrected scetch of my code:

                       

                      ........................ START ........................

                       

                      some global variables

                       

                      app.doScript(checkSelection, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, "Process Table");

                       

                      1. function checkSelection () {
                      2.     - loop - number of selected objects
                      3.         - condition 1 - if no selection
                      4.         - condition 2 - elseif no text frame selected
                      5.         - condition 3 - elseif no table inside
                      6.    myTables = allSelection[i].tables.everyItem();
                      7.     createObjectStyle()
                      8.     runAll()
                      9. }
                      10. function runAll () {
                      11.     - loop - number of selected objects
                      12.         clearOverrides();
                      13.         tableStyles();
                      14.         cellStyles();
                      15. }
                      16. function clearOverrides () {
                      17.     - using myTables
                      18. }
                      19. function cellStyles () {
                      20.     - using myTables
                      21. }
                      22. function tableStyles () {
                      23.     - using myTables
                      24. }
                      25. function createObjectStyle () {
                      26. }

                       

                      ........................ END ........................

                       

                      (I didn´t use the javascript code-style to have the possibility to mark some important things.)

                       

                      In this case it crashes: "undefined is not an object" (myTables).

                      Would I put myTables in the loop whith an else (after line 5) it would be accepted. But it doesn´t make sense to create that variable in a loop, isn´t it? So not the Object Styles (line 7).

                       

                      The task: I need the first loop to check if and what is selected. If the right object(s) is/are selected (textframe contains a table) it/there should be formatted.