8 Replies Latest reply on May 23, 2017 7:21 AM by laguna92651

    Modifying Javascript To Plot in a Web Viewer

    laguna92651

      I am in the process of learning to do charting with the d3 library, however I'm not developing for a web page but to chart in a Filemaker database.

      I have the following code from a d3 charting tutorial, which plots a bar chart. (Only showing the first part of the code, don't believe the rest is relevant?)

      I am using a FileMaker web viewer and Execute SQL to grab and format the data from Filemaker to put into an array that matches the hard coded data shown in the example code, I have the d3.min.js library on the layout.

       

      The code works fine in Filemaker with the hard coded data, shown here, commented out on line 66, var dataset = [ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13, 11, 12, 15, 20, 18, 17, 16, 18, 23, 25 ];.

      When I replaced the hard coded data with the lines below, the Execute SQL generated array is placed in the global variable merge field <<$$D3.DATA.SORT2>>. The Execute SQL array looks like the hard coded data array.

       

      Line 63

          var sort2 = [<<$$D3.DATA.SORT2>>];

          var dataset = d3.entries(sort2);

       

      I do not get the chart. Removing the css section doesn't seem to make a difference, hard coded data works and SQL generated data still does not work with the css portion removed.

      Is there something I have to remove or add to the code?  Is there a way to see the data that I'm bringing in from Excute SQL in javascript?

       

      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="utf-8">
          <title>D3: Ascending and descending sorts</title>
          <script type="text/javascript" src="d3.js"></script>
          <style type="text/css">
      
      //The <head></head>is the css code
      
              body {
                  background-color: gray;
              }
              /* New rules for styling buttons */
              #buttonContainer {
                  margin-bottom: 10px;
              }
              button {
                  padding: 15px;
              }
              svg {
                  background-color: white;
              }
              g.bar text {
                  font-family: sans-serif;
                  font-size: 11px;
                  fill: white;
                  font-style: bold;
                  text-anchor: middle;
                  opacity: 0;
              }
              g.bar.highlight text {
                  opacity: 1;
              }
              g.bar.highlight rect {
                  fill: Maroon;
              }
              .axis path,
              .axis line {
                  fill: none;
                  stroke: black;
                  shape-rendering: crispEdges;
              }
              .axis text {
                  font-family: sans-serif;
                  font-size: 11px;
              }
          </style>
      </head>
      <body>
          <!-- New buttons to trigger sorting! -->
          <div id="buttonContainer">
              <button id="sortAscending">Sort Ascending</button>
              <button id="sortDescending">Sort Descending</button>
          </div>
          <script type="text/javascript">
              //Width, height, padding
              var w = 600;
              var h = 250;
              var padding = 25;
      
              //Array of data values
                        var sort2 = [<<$$D3.DATA.SORT2>>];
                        var dataset = d3.entries(sort2);
      
              /*var dataset = [ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13,
                              11, 12, 15, 20, 18, 17, 16, 18, 23, 25 ];*/
      
              //Configure x and y scale functions
              var xScale = d3.scale.ordinal()
                              .domain(d3.range(dataset.length))
                              .rangeRoundBands([ padding, w - padding ], 0.05);
              var yScale = d3.scale.linear()
                              .domain([ 0, d3.max(dataset) ])
                              .rangeRound([ h - padding, padding ]);
              //Configure y axis generator
              var yAxis = d3.svg.axis()
                              .scale(yScale)
                              .orient("left")
                              .ticks(5);
              //Create SVG element
              var svg = d3.select("body")
                          .append("svg")
                          .attr("width", w)
                          .attr("height", h);
              var xScale = d3.scale.ordinal()
                              .domain(d3.range(dataset.length))
                              .rangeRoundBands([ padding, w - padding ], 0.05);
              var yScale = d3.scale.linear()
                              .domain([ 0, d3.max(dataset) ])
                              .rangeRound([ h - padding, padding ]);
              //Configure y axis generator
              var yAxis = d3.svg.axis()
                              .scale(yScale)
                              .orient("left")
                              .ticks(5);
              //Create SVG element
              var svg = d3.select("body")
                          .append("svg")
                          .attr("width", w)
                          .attr("height", h);
      
        • 1. Re: Modifying Javascript To Plot in a Web Viewer
          erolst

          Keep in mind that the JavaScript is just a dumb string, as far as FileMaker us concerned. If you put a FileMaker object reference into that, it is regarded and evaluated just as text, instead of an expression.

           

          What you need to do is concenate the text lliterals with the dynamic references, i.e. like

           

          "Beginning jscode" & $$aFileMakerArrayVar & "continuing js code" & anotherFileMakerExpression & "more js code"

           

          etc.

           

          If you have Advanced, calculate your result into a variable and inspect it in the Data Viewer; if not, calculate it in a calc field and inspect its content.

          1 of 1 people found this helpful
          • 2. Re: Modifying Javascript To Plot in a Web Viewer
            laguna92651

            Thanks erolst, I had checked the data in the web viewer and it was in the format I needed.

             

            The problem seemed to be using d3.entries(sort2)

            The entries() "Returns an array containing the property keys and values of the specified object (an associative array)."  More infor here: Arrays - D3 wiki

             

            I am assuming since my data was in this format, var dataset = [ 5, 10, 13, 19, 21, 25]; the entries() wasn't manipulating the data set properly. I set the FM variable equal to the var dataset and the chart is now plotting from my SQL statement.

             

            var dataset = [<<$$D3.DATA.SORT2>>];

             

            Is it correct to assume that I can always just set the FM variable equal to the javascript var, as long as the FM variable is in the array format that the javascript code is expecting?

            • 3. Re: Modifying Javascript To Plot in a Web Viewer
              erolst

              laguna92651 wrote:

               

              var dataset = [<<$$D3.DATA.SORT2>>];

               

              Is it correct to assume that I can always just set the FM variable equal to the javascript var, as long as the FM variable is in the array format that the javascript code is expecting?

              Yes and no; yes because the data is in the right format, but no because - and that was the gist of my previous answer - you need to mix static string parts and dynamic references in the proper way. That snippet from above should probably read:

               

              "var dataset = [" & $$D3.DATA.SORT2 & "];"

               

              If we assume that your FileMaker global var $$D3.DATA.SORT2 contains a comma-separated list of numeric values, like "1,3,5,7,9", the above expression will return

               

              var dataset = [1,3,5,7,9];

               

              It's basically about the difference between the bare expressions SomeTable::someField and "SomeTable::someField".

               

              The first will yield whatever value the referenced field holds at runtime; the second one will always yield "SomeTable::someField", since it's not a reference, but a string. (Leaving aside the fact that you can use GetField() or Evaluate() to resolve a textual field reference.)

               

              btw, I'm not sure why you are using the layout merge symbols with the variable name. If your variable name is $$D3.DATA.SORT2, then use just that.

              • 4. Re: Modifying Javascript To Plot in a Web Viewer
                beverly

                I may do something like this:

                JavaScript is one long string, but there are parts that are static (always the same) and just one part that changes (your generated array.

                 

                As part of you calculation you might store the JavaScript (and the rest of your HTML) into two separate chunks (variables, global fields).

                1. $code1 = Everything from the beginning up to where your $$D3.DATA.SORT2 is inserted

                2. $code2 = from the end of where you inserted your $$variable to the end of the rest of the code.

                 

                Then your final value is:

                 

                $code1 & $$D3.DATA.SORT2 & $code2

                 

                If I have more than one place to change, then go with erolst's method (or something else).

                 

                Beverly

                • 5. Re: Modifying Javascript To Plot in a Web Viewer
                  user19752

                  The merge symbols may be used for

                   

                  Substitute ( "html text" ;

                  [ "<<$variableInHTML>>" ; $fmVariable ]

                  ...

                  )

                  • 6. Re: Modifying Javascript To Plot in a Web Viewer
                    laguna92651

                    Could you elaborate a little, not sure what your referring to, thanks.

                    • 7. Re: Modifying Javascript To Plot in a Web Viewer
                      user19752

                      You need to concatenate FM variable with rest of HTML code like as they wrote.

                      "<html><script>var v=[" & $var & "]</script>"

                      Substituting is another way to get same result.

                      Substitute (

                      "<html><script>var v=[<<$var>>]</script>" ;

                      "<<$var>>" ; $var )

                      This have some advantage on readability (for someones), but need taking care the embedded <<$var>> style string never appear in other context.

                      • 8. Re: Modifying Javascript To Plot in a Web Viewer
                        laguna92651

                        Great, thanks for the help.